Skip to content

Commit 619d624

Browse files
committed
Merge branch 'release/2.2.0'
2 parents 6361f2d + 485e7c9 commit 619d624

File tree

6 files changed

+60
-24
lines changed

6 files changed

+60
-24
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ node_js:
33
- "0.10"
44
- "0.12"
55
- "4"
6-
- "5"
6+
- "6"
77
services:
88
- redis-server
99
install:

History.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111

1212
## v1.0.1 / 2014-03-14
1313

14-
* fix race condition resetting the keys
14+
* fix race condition resetting the keys.

Readme.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
[![Build Status](https://travis-ci.org/tj/node-ratelimiter.svg)](https://travis-ci.org/tj/node-ratelimiter)
66

77
## Release Notes
8-
[v2.1.3](https://github.com/tj/node-ratelimiter/tree/v2.1.3) - [#22](/../../pull/22) by [@coderhaoxin](https://github.com/coderhaoxin) - Dev dependencies versions bump
8+
[v2.2.0](https://github.com/tj/node-ratelimiter/tree/v2.2.0) - [#30](/../../pull/30) by [@kp96](https://github.com/kp96) - Race condition when using `async.times`.
99

10-
[v2.1.2](https://github.com/tj/node-ratelimiter/tree/v2.1.2) - [#17](/../../pull/17) by [@waleedsamy](https://github.com/waleedsamy) - Add Travis CI support
10+
[v2.1.3](https://github.com/tj/node-ratelimiter/tree/v2.1.3) - [#22](/../../pull/22) by [@coderhaoxin](https://github.com/coderhaoxin) - Dev dependencies versions bump.
1111

12-
[v2.1.1](https://github.com/tj/node-ratelimiter/tree/v2.1.1) - [#13](/../../pull/13) by [@kwizzn](https://github.com/kwizzn) - Fixes out-of-sync TTLs after running decr()
12+
[v2.1.2](https://github.com/tj/node-ratelimiter/tree/v2.1.2) - [#17](/../../pull/17) by [@waleedsamy](https://github.com/waleedsamy) - Add Travis CI support.
1313

14-
[v2.1.0](https://github.com/tj/node-ratelimiter/tree/v2.1.0) - [#12](/../../pull/12) by [@luin](https://github.com/luin) - Adding support for ioredis
14+
[v2.1.1](https://github.com/tj/node-ratelimiter/tree/v2.1.1) - [#13](/../../pull/13) by [@kwizzn](https://github.com/kwizzn) - Fixes out-of-sync TTLs after running decr().
15+
16+
[v2.1.0](https://github.com/tj/node-ratelimiter/tree/v2.1.0) - [#12](/../../pull/12) by [@luin](https://github.com/luin) - Adding support for ioredis.
1517

1618
[v2.0.1](https://github.com/tj/node-ratelimiter/tree/v2.0.1) - [#9](/../../pull/9) by [@ruimarinho](https://github.com/ruimarinho) - Update redis commands to use array notation.
1719

index.js

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ function Limiter(opts) {
3636
* @api public
3737
*/
3838

39-
Limiter.prototype.inspect = function () {
40-
return '<Limiter id='
41-
+ this.id + ', duration='
42-
+ this.duration + ', max='
43-
+ this.max + '>';
39+
Limiter.prototype.inspect = function() {
40+
return '<Limiter id=' +
41+
this.id + ', duration=' +
42+
this.duration + ', max=' +
43+
this.max + '>';
4444
};
4545

4646
/**
@@ -57,7 +57,7 @@ Limiter.prototype.inspect = function () {
5757
* @api public
5858
*/
5959

60-
Limiter.prototype.get = function (fn) {
60+
Limiter.prototype.get = function(fn) {
6161
var count = this.prefix + 'count';
6262
var limit = this.prefix + 'limit';
6363
var reset = this.prefix + 'reset';
@@ -72,7 +72,7 @@ Limiter.prototype.get = function (fn) {
7272
.set([count, max, 'PX', duration, 'NX'])
7373
.set([limit, max, 'PX', duration, 'NX'])
7474
.set([reset, ex, 'PX', duration, 'NX'])
75-
.exec(function (err, res) {
75+
.exec(function(err, res) {
7676
if (err) return fn(err);
7777

7878
// If the request has failed, it means the values already
@@ -104,21 +104,22 @@ Limiter.prototype.get = function (fn) {
104104
}
105105

106106
db.multi()
107-
.set([count, n - 1, 'PX', ex * 1000 - dateNow, 'XX'])
107+
.decr(count)
108+
.pexpire([count, ex * 1000 - dateNow])
108109
.pexpire([limit, ex * 1000 - dateNow])
109110
.pexpire([reset, ex * 1000 - dateNow])
110-
.exec(function (err, res) {
111+
.exec(function(err, res) {
111112
if (err) return fn(err);
112113
if (isFirstReplyNull(res)) return mget();
113-
n = n - 1;
114+
n = Array.isArray(res[0]) ? ~~res[0][1] : ~~res[0];
114115
done();
115116
});
116117
}
117118

118119
function mget() {
119-
db.watch([count], function (err) {
120+
db.watch([count], function(err) {
120121
if (err) return fn(err);
121-
db.mget([count, limit, reset], function (err, res) {
122+
db.mget([count, limit, reset], function(err, res) {
122123
if (err) return fn(err);
123124
if (!res[0] && res[0] !== 0) return create();
124125

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ratelimiter",
3-
"version": "2.1.3",
3+
"version": "2.2.0",
44
"repository": "visionmedia/node-ratelimiter",
55
"description": "abstract rate limiter backed by redis",
66
"keywords": [
@@ -9,8 +9,12 @@
99
"limiter",
1010
"limit"
1111
],
12+
"scripts": {
13+
"test": "mocha"
14+
},
1215
"dependencies": {},
1316
"devDependencies": {
17+
"async": "2.1.4",
1418
"ioredis": "1.15.1",
1519
"mocha": "*",
1620
"redis": "2.6.0-1",

test/index.js

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
require('should');
2-
var Limiter = require('..');
2+
var Limiter = require('..'),
3+
async = require('async');
34

45
// Uncomment the following line if you want to see
56
// debug logs from the node-redis module.
67
//redis.debug_mode = true;
78

8-
['redis', 'ioredis'].forEach(function (redisModuleName) {
9+
['redis', 'ioredis'].forEach(function(redisModuleName) {
910
var redisModule = require(redisModuleName);
1011
var db = require(redisModuleName).createClient();
1112
describe('Limiter with ' + redisModuleName, function() {
@@ -146,7 +147,7 @@ var Limiter = require('..');
146147
.pttl(['limit:something:count'])
147148
.pttl(['limit:something:limit'])
148149
.pttl(['limit:something:reset'])
149-
.exec(function (err, res) {
150+
.exec(function(err, res) {
150151
if (err) return done(err);
151152
var ttlCount = (typeof res[0] === 'number') ? res[0] : res[0][1];
152153
var ttlLimit = (typeof res[1] === 'number') ? res[1] : res[1][1];
@@ -211,7 +212,8 @@ var Limiter = require('..');
211212

212213
if (err) {
213214
done(err);
214-
} else {
215+
}
216+
else {
215217
responses.forEach(function(res) {
216218
res[1].remaining.should.equal(left < 0 ? 0 : left);
217219
left--;
@@ -230,7 +232,8 @@ var Limiter = require('..');
230232
limits[0].get(function(err, res) {
231233
if (err) {
232234
done(err);
233-
} else {
235+
}
236+
else {
234237
res.remaining.should.equal(left--);
235238

236239
// Simulate multiple concurrent requests.
@@ -241,5 +244,31 @@ var Limiter = require('..');
241244
});
242245
});
243246
});
247+
248+
describe('when limiter is called in parallel by multiple clients', function() {
249+
var max = 6,
250+
limiter;
251+
252+
limiter = new Limiter({
253+
duration: 10000,
254+
max: max,
255+
id: 'asyncsomething',
256+
db: redisModule.createClient()
257+
});
258+
259+
it('should set the count properly without race conditions', function(done) {
260+
async.times(max, function(n, next) {
261+
limiter.get(next);
262+
},
263+
function(errs, limits) {
264+
265+
limits.forEach(function(limit) {
266+
limit.remaining.should.equal(max--);
267+
});
268+
done();
269+
270+
});
271+
});
272+
})
244273
});
245274
});

0 commit comments

Comments
 (0)