Skip to content
This repository was archived by the owner on Dec 1, 2022. It is now read-only.

Commit 1a5440a

Browse files
committed
Bug fix and refactor so that the 'min' value is respected when it is greater than 1 and there is no actual capacity being utilised
#4
1 parent 357123d commit 1a5440a

File tree

6 files changed

+123
-78
lines changed

6 files changed

+123
-78
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
"linebreak-style": 2,
7373
"lines-around-comment": 0,
7474
"max-depth": 0,
75-
"max-len": [2, 80, 4],
75+
"max-len": [2, 100, 4],
7676
"max-nested-callbacks": 0,
7777
"max-params": 0,
7878
"max-statements": 0,

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ implementation.
140140

141141
This project has the following main dependencies:
142142
+ aws-sdk - Access to AWS services
143-
+ winston - Logging
144143
+ dotenv - Environment variable configuration useful for lambda
145144
+ measured - Statistics gathering
146145

make-webpack-config.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ module.exports = function(options) {
1616
var alias = {};
1717
var aliasLoader = {};
1818
var externals = [
19-
{ 'aws-sdk': 'commonjs aws-sdk' }, // This is already available on the lambda server
20-
{ 'winston': 'commonjs winston' } // Winston looks for its own package.json
19+
{ 'aws-sdk': 'commonjs aws-sdk' } // This is already available on the lambda server
2120
];
2221
var modulesDirectories = ['node_modules', 'web_modules'];
2322
var extensions = ["", ".web.js", ".js", ".jsx", ".json"];

src/Config.js

Lines changed: 109 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -3,104 +3,148 @@ import RateLimitedDecrement from './RateLimitedDecrement';
33
import Throughput from './Throughput';
44
import { invariant } from '../src/Global';
55

6+
// NOTES
7+
// - 'adjustmentPercent' or 'adjustmentUnits' is used, which ever is bigger
8+
// - 'min' and 'max' are hard limits
9+
// - 'minAdjustment' is minimum possible downward adjustment, there is no point
10+
// wasting 1 of 4 daily decrements on a small value
11+
12+
const config = {
13+
readCapacity: {
14+
min: 1,
15+
max: 10,
16+
increment: {
17+
thresholdPercent: 90,
18+
adjustmentPercent: 100,
19+
adjustmentUnits: 3,
20+
},
21+
decrement: {
22+
thresholdPercent: 30,
23+
minAdjustment: 3,
24+
minGracePeriodAfterLastIncrementMinutes: 60,
25+
minGracePeriodAfterLastDecrementMinutes: 60,
26+
},
27+
},
28+
writeCapacity: {
29+
min: 1,
30+
max: 10,
31+
increment: {
32+
adjustmentPercent: 100,
33+
adjustmentUnits: 3,
34+
},
35+
decrement: {
36+
thresholdPercent: 30,
37+
minAdjustment: 3,
38+
minGracePeriodAfterLastIncrementMinutes: 60,
39+
minGracePeriodAfterLastDecrementMinutes: 60,
40+
},
41+
},
42+
};
43+
644
const provisioner = new ConfigurableProvisioner({
745
readCapacity: {
846
increment: {
947
isAdjustmentRequired: (data, calcFunc) => {
10-
invariant(typeof data !== 'undefined',
11-
'Parameter \'data\' is not set');
12-
invariant(typeof calcFunc !== 'undefined',
13-
'Parameter \'calcFunc\' is not set');
48+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
49+
invariant(typeof calcFunc !== 'undefined', 'Parameter \'calcFunc\' is not set');
1450

15-
return Throughput.getReadCapacityUtilisationPercent(data) > 90;
51+
let isAboveThreshold = Throughput.getReadCapacityUtilisationPercent(data) >
52+
config.readCapacity.increment.thresholdPercent;
53+
54+
let isBelowMin = data.ProvisionedThroughput.ReadCapacityUnits <
55+
config.readCapacity.min;
56+
57+
return isAboveThreshold || isBelowMin;
1658
},
1759
calculateValue: data => {
18-
invariant(typeof data !== 'undefined',
19-
'Parameter \'data\' is not set');
20-
21-
// adjustmentPercent or adjustmentUnits is used, which ever is bigger
22-
const adjustmentPercent = 100;
23-
const adjustmentUnits = 3;
24-
// min and max hard limits
25-
const max = 10;
26-
const min = 1;
60+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
61+
2762
return Throughput.getPercentAdjustedReadCapacityUnits(
28-
data, adjustmentPercent, adjustmentUnits, max, min);
63+
data,
64+
config.readCapacity.increment.adjustmentPercent,
65+
config.readCapacity.increment.adjustmentUnits,
66+
config.readCapacity.max,
67+
config.readCapacity.min);
2968
},
3069
},
3170
decrement: {
3271
isAdjustmentRequired: (data, calcFunc) => {
33-
invariant(typeof data !== 'undefined',
34-
'Parameter \'data\' is not set');
35-
invariant(typeof calcFunc !== 'undefined',
36-
'Parameter \'calcFunc\' is not set');
37-
38-
// minimum possible downward adjustment, there is no point
39-
// wasting 1 of 4 daily decrements on a small value
40-
const minAdjustment = 3;
41-
const minGracePeriodAfterLastIncrementMinutes = 60;
42-
const minGracePeriodAfterLastDecrementMinutes = 60;
43-
return Throughput.getReadCapacityUtilisationPercent(data) < 30 &&
72+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
73+
invariant(typeof calcFunc !== 'undefined', 'Parameter \'calcFunc\' is not set');
74+
75+
let isReadDecrementAllowed =
4476
RateLimitedDecrement.isReadDecrementAllowed(
45-
data, calcFunc, minAdjustment,
46-
minGracePeriodAfterLastIncrementMinutes,
47-
minGracePeriodAfterLastDecrementMinutes);
77+
data,
78+
calcFunc,
79+
config.readCapacity.decrement.minAdjustment,
80+
config.readCapacity.decrement.minGracePeriodAfterLastIncrementMinutes,
81+
config.readCapacity.decrement.minGracePeriodAfterLastDecrementMinutes);
82+
83+
let isBelowThreshold = Throughput.getReadCapacityUtilisationPercent(data) <
84+
config.readCapacity.decrement.thresholdPercent;
85+
86+
let isAboveMax = data.ProvisionedThroughput.ReadCapacityUnits >
87+
config.readCapacity.max;
88+
89+
return isReadDecrementAllowed && (isBelowThreshold || isAboveMax);
4890
},
4991
calculateValue: data => {
50-
invariant(typeof data !== 'undefined',
51-
'Parameter \'data\' is not set');
92+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
5293

53-
return Math.max(data.ConsumedThroughput.ReadCapacityUnits, 1);
94+
return Math.max(data.ConsumedThroughput.ReadCapacityUnits, config.readCapacity.min);
5495
},
5596
}
5697
},
5798
writeCapacity: {
5899
increment: {
59100
isAdjustmentRequired: (data, calcFunc) => {
60-
invariant(typeof data !== 'undefined',
61-
'Parameter \'data\' is not set');
62-
invariant(typeof calcFunc !== 'undefined',
63-
'Parameter \'calcFunc\' is not set');
101+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
102+
invariant(typeof calcFunc !== 'undefined', 'Parameter \'calcFunc\' is not set');
64103

65-
return Throughput.getWriteCapacityUtilisationPercent(data) > 90;
104+
let isAboveThreshold = Throughput.getWriteCapacityUtilisationPercent(data) >
105+
config.writeCapacity.increment.thresholdPercent;
106+
107+
let isBelowMin = data.ProvisionedThroughput.WriteCapacityUnits <
108+
config.writeCapacity.min;
109+
110+
return isAboveThreshold || isBelowMin;
66111
},
67112
calculateValue: data => {
68-
invariant(typeof data !== 'undefined',
69-
'Parameter \'data\' is not set');
70-
71-
// adjustmentPercent or adjustmentUnits is used, which ever is bigger
72-
const adjustmentPercent = 100;
73-
const adjustmentUnits = 3;
74-
// min and max hard limits
75-
const max = 10;
76-
const min = 1;
113+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
114+
77115
return Throughput.getPercentAdjustedWriteCapacityUnits(
78-
data, adjustmentPercent, adjustmentUnits, max, min);
116+
data,
117+
config.writeCapacity.increment.adjustmentPercent,
118+
config.writeCapacity.increment.adjustmentUnits,
119+
config.writeCapacity.max,
120+
config.writeCapacity.min);
79121
},
80122
},
81123
decrement: {
82124
isAdjustmentRequired: (data, calcFunc) => {
83-
invariant(typeof data !== 'undefined',
84-
'Parameter \'data\' is not set');
85-
invariant(typeof calcFunc !== 'undefined',
86-
'Parameter \'calcFunc\' is not set');
87-
88-
// minimum possible downward adjustment, there is no point
89-
// wasting 1 of 4 daily decrements on a small value
90-
const minAdjustment = 3;
91-
const minGracePeriodAfterLastIncrementMinutes = 60;
92-
const minGracePeriodAfterLastDecrementMinutes = 60;
93-
return Throughput.getWriteCapacityUtilisationPercent(data) < 30 &&
125+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
126+
invariant(typeof calcFunc !== 'undefined', 'Parameter \'calcFunc\' is not set');
127+
128+
let isWriteDecrementAllowed =
94129
RateLimitedDecrement.isWriteDecrementAllowed(
95-
data, calcFunc, minAdjustment,
96-
minGracePeriodAfterLastIncrementMinutes,
97-
minGracePeriodAfterLastDecrementMinutes);
130+
data,
131+
calcFunc,
132+
config.writeCapacity.decrement.minAdjustment,
133+
config.writeCapacity.decrement.minGracePeriodAfterLastIncrementMinutes,
134+
config.writeCapacity.decrement.minGracePeriodAfterLastDecrementMinutes);
135+
136+
let isBelowThreshold = Throughput.getWriteCapacityUtilisationPercent(data) <
137+
config.writeCapacity.decrement.thresholdPercent;
138+
139+
let isAboveMax = data.ProvisionedThroughput.WriteCapacityUnits >
140+
config.writeCapacity.max;
141+
142+
return isWriteDecrementAllowed && (isBelowThreshold || isAboveMax);
98143
},
99144
calculateValue: data => {
100-
invariant(typeof data !== 'undefined',
101-
'Parameter \'data\' is not set');
145+
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
102146

103-
return Math.max(data.ConsumedThroughput.WriteCapacityUnits, 1);
147+
return Math.max(data.ConsumedThroughput.WriteCapacityUnits, config.writeCapacity.min);
104148
},
105149
}
106150
}
@@ -125,8 +169,7 @@ export default {
125169
}
126170
},
127171
getTableUpdate: (description, consumedCapacityDescription) => {
128-
invariant(typeof description !== 'undefined',
129-
'Parameter \'description\' is not set');
172+
invariant(typeof description !== 'undefined', 'Parameter \'description\' is not set');
130173
invariant(typeof consumedCapacityDescription !== 'undefined',
131174
'Parameter \'consumedCapacityDescription\' is not set');
132175

src/Global.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import measured from 'measured';
22
import _warning from 'warning';
33
import _invariant from 'invariant';
4-
import { Console } from 'console';
5-
6-
const logger = new Console(process.stdout, process.stderr);
74

85
export const json = { padding: 0 };
96

107
export const stats = measured.createCollection();
118

129
export const log = (...params) => {
13-
logger.log(...params);
10+
// eslint-disable-next-line no-console
11+
console.log(...params);
1412
};
1513

1614
export const warning = (predicateOrValue, value) => {

src/Throughput.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export default class Throughput {
2020
invariant(typeof max !== 'undefined', 'Parameter \'max\' is not set');
2121
invariant(typeof min !== 'undefined', 'Parameter \'min\' is not set');
2222

23+
if (data.ProvisionedThroughput.ReadCapacityUnits < min) {
24+
return min;
25+
}
26+
2327
let units = Math.round(
2428
data.ProvisionedThroughput.ReadCapacityUnits * (adjustmentPercent / 100));
2529
units = Math.max(units, adjustmentUnits);
@@ -41,13 +45,15 @@ export default class Throughput {
4145
invariant(typeof data !== 'undefined', 'Parameter \'data\' is not set');
4246
invariant(typeof adjustmentPercent !== 'undefined',
4347
'Parameter \'adjustmentPercent\' is not set');
44-
invariant(typeof adjustmentUnits !== 'undefined',
45-
'Parameter \'adjustmentUnits\' is not set');
48+
invariant(typeof adjustmentUnits !== 'undefined', 'Parameter \'adjustmentUnits\' is not set');
4649
invariant(typeof max !== 'undefined', 'Parameter \'max\' is not set');
4750
invariant(typeof min !== 'undefined', 'Parameter \'min\' is not set');
4851

49-
let units = Math.round(
50-
data.ProvisionedThroughput.WriteCapacityUnits *
52+
if (data.ProvisionedThroughput.WriteCapacityUnits < min) {
53+
return min;
54+
}
55+
56+
let units = Math.round(data.ProvisionedThroughput.WriteCapacityUnits *
5157
(adjustmentPercent / 100));
5258

5359
units = Math.max(units, adjustmentUnits);

0 commit comments

Comments
 (0)