This repository has been archived by the owner on Mar 1, 2021. It is now read-only.
forked from channl/dynamodb-lambda-autoscale
-
Notifications
You must be signed in to change notification settings - Fork 0
/
RateLimitedDecrement.js
119 lines (95 loc) · 4.23 KB
/
RateLimitedDecrement.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* @flow */
import { invariant } from '../Global';
import type {
TableProvisionedAndConsumedThroughput,
AdjustmentContext
} from '../flow/FlowTypes';
export default class RateLimitedDecrement {
static isDecrementAllowed(
data: TableProvisionedAndConsumedThroughput,
adjustmentContext: AdjustmentContext,
calcNewValueFunc: (data: TableProvisionedAndConsumedThroughput) => number) {
invariant(data != null, 'Parameter \'data\' is not set');
invariant(adjustmentContext != null, 'Parameter \'adjustmentContext\' is not set');
invariant(calcNewValueFunc != null, 'Parameter \'calcNewValueFunc\' is not set');
if (this.getNextAllowedDecrementDate(data, adjustmentContext) > this.getNowDate()) {
// Disallow if we havent crossed one of four time barriers
return false;
}
let adjustment = Math.abs(adjustmentContext.ProvisionedValue) -
Math.abs(calcNewValueFunc(data));
if (adjustmentContext.CapacityAdjustmentConfig != null &&
adjustmentContext.CapacityAdjustmentConfig.When.UnitAdjustmentGreaterThan != null &&
adjustment <= adjustmentContext.CapacityAdjustmentConfig.When.UnitAdjustmentGreaterThan &&
this.getNowDate().valueOf() <
this.getLastAllowedDecrementDate().valueOf()) {
// Disallow if the adjustment is very small.
// However, if we have crossed the last time
// barrier of the day then we might as well allow it.
return false;
}
return true;
}
static getNextAllowedDecrementDate(
data: TableProvisionedAndConsumedThroughput,
adjustmentContext: AdjustmentContext) {
// Check if we have already had all the decreases we are allowed today
if (data.ProvisionedThroughput.NumberOfDecreasesToday >= 4) {
return this.getTomorrowDate();
}
// Get the last decrease or start of day
let lastDecrease = this.parseDate(data.ProvisionedThroughput.LastDecreaseDateTime);
let lastDecrementDate = this.getLastDecrementDate(lastDecrease);
// Get the next allowed decrement
let lastAllowedDecrementDate = this.getLastAllowedDecrementDate();
let periodMs = lastAllowedDecrementDate.valueOf() - lastDecrementDate.valueOf();
let periodMs2 = periodMs / (5 - data.ProvisionedThroughput.NumberOfDecreasesToday);
let nextDecrementDate = this.getLastDecrementDate(lastDecrease);
nextDecrementDate.setMilliseconds(nextDecrementDate.getMilliseconds() + periodMs2);
// Handle grace periods
let withIncrementGracePeriod = this.parseDate(data.ProvisionedThroughput.LastIncreaseDateTime);
if (adjustmentContext.CapacityAdjustmentConfig != null &&
adjustmentContext.CapacityAdjustmentConfig.When.AfterLastIncrementMinutes != null) {
let incMins = adjustmentContext.CapacityAdjustmentConfig.When.AfterLastIncrementMinutes;
withIncrementGracePeriod.setMinutes(withIncrementGracePeriod.getMinutes() + incMins);
}
let withDecrementGracePeriod = this.parseDate(data.ProvisionedThroughput.LastDecreaseDateTime);
if (adjustmentContext.CapacityAdjustmentConfig != null &&
adjustmentContext.CapacityAdjustmentConfig.When.AfterLastDecrementMinutes != null) {
let decMins = adjustmentContext.CapacityAdjustmentConfig.When.AfterLastDecrementMinutes;
withDecrementGracePeriod.setMinutes(withDecrementGracePeriod.getMinutes() + decMins);
}
let result = new Date(Math.max(
nextDecrementDate, withIncrementGracePeriod, withDecrementGracePeriod));
return result;
}
static getNowDate() {
return new Date(Date.now());
}
static getTodayDate() {
let value = this.getNowDate();
value.setHours(0, 0, 0, 0);
return value;
}
static getTomorrowDate() {
let value = this.getTodayDate();
value.setDate(value.getDate() + 1);
return value;
}
static getLastAllowedDecrementDate() {
let value = this.getTodayDate();
value.setHours(23, 30, 0, 0);
return value;
}
static getLastDecrementDate(lastDecrease) {
let today = this.getTodayDate();
return lastDecrease < today ? today : new Date(lastDecrease.valueOf());
}
static parseDate(value) {
// eslint-disable-next-line eqeqeq
if (typeof value === 'undefined' || value == null) {
return new Date(-8640000000000000);
}
return new Date(Date.parse(value));
}
}