Skip to content

Commit 504a1ad

Browse files
committed
allow a discrete refilling rate
1 parent b13186a commit 504a1ad

2 files changed

Lines changed: 54 additions & 3 deletions

File tree

lib/db.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ function normalizeType(params) {
2424
'per_interval',
2525
'interval',
2626
'size',
27-
'unlimited'
27+
'unlimited',
28+
'discrete'
2829
]);
2930

3031
INTERVAL_SHORTCUTS.forEach(ish => {
@@ -100,7 +101,11 @@ class LimitDB {
100101
const now = Date.now();
101102
const deltaMS = Math.max(now - bucket.lastDrip, 0);
102103
const dripAmount = deltaMS * (type.per_interval / type.interval);
103-
const content = Math.min(bucket.content + dripAmount, type.size);
104+
var content = bucket.content;
105+
106+
if (!type.discrete || dripAmount >= type.per_interval) {
107+
content = Math.floor(Math.min(bucket.content + dripAmount, type.size));
108+
}
104109

105110
return {
106111
content: content,
@@ -204,7 +209,7 @@ class LimitDB {
204209
if (err) { return callback(err); }
205210
callback(null, {
206211
conformant: bucket.lastConformant,
207-
remaining: Math.floor(bucket.content),
212+
remaining: bucket.content,
208213
reset: bucket.reset,
209214
limit: typeParams.size
210215
});

test/discrete_example.tests.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const LimitDB = require('../lib/db');
2+
const MockDate = require('mockdate');
3+
const assert = require('chai').assert;
4+
5+
const types = {
6+
ip: {
7+
size: 5,
8+
per_interval: 5,
9+
interval: 500,
10+
discrete: true
11+
}
12+
};
13+
14+
describe('when the fill rate is discrete', () => {
15+
afterEach(function () {
16+
MockDate.reset();
17+
});
18+
19+
const db = new LimitDB({
20+
inMemory: true,
21+
types
22+
});
23+
24+
beforeEach(function(done) {
25+
MockDate.set(Date.now());
26+
db.take({ type: 'ip', key: '21.17.65.41', count: 5 }, done);
27+
});
28+
29+
it('should not add less than the per_interval amount', function(done) {
30+
MockDate.set(Date.now() + 150);
31+
db.status({ type: 'ip', prefix: '21.17.65.41' }, (err, result) => {
32+
if (err) { return done(err); }
33+
assert.equal(result.items[0].remaining, 0);
34+
done();
35+
});
36+
});
37+
38+
it('should add the per_interval amount after the elapsed interval', function(done) {
39+
MockDate.set(Date.now() + 500);
40+
db.status({ type: 'ip', prefix: '21.17.65.41' }, (err, result) => {
41+
if (err) { return done(err); }
42+
assert.equal(result.items[0].remaining, 5);
43+
done();
44+
});
45+
});
46+
});

0 commit comments

Comments
 (0)