Skip to content

Commit ad4975e

Browse files
committed
Merge pull request #434 from CodeNow/redis-locks-ttl
Redis locks ttl
2 parents 5eb5c9c + dfe9831 commit ad4975e

3 files changed

Lines changed: 101 additions & 3 deletions

File tree

configs/.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
LOG_ERRORS=true
22
TOKEN_EXPIRES="1 year"
33
REDIS_KEY_EXPIRES="5 minutes"
4+
REDIS_LOCK_EXPIRES="6 minutes"
45
DOCK_PROJECT_LIMIT=100000000
56
DEPLOY_COMMAND="echo DEPLOY"
67
COOKIE_SECRET="\$up3r,$3<r3t"

lib/models/redis/mutex.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@ function RedisMutex (key) {
99
}
1010

1111
RedisMutex.prototype.lock = function (cb) {
12-
this.redis.setnx(this.key, 'lock', function (err, success) {
13-
cb(err, success === '1');
12+
// SET resource-name anystring NX EX max-lock-time
13+
// Is a simple way to implement a locking system with Redis.
14+
// See http://redis.io/commands/set
15+
var expires = process.env.REDIS_LOCK_EXPIRES;
16+
this.redis.set(this.key, 'lock', 'NX', 'PX', expires, function (err, success) {
17+
cb(err, success === 'OK');
1418
});
1519
};
1620

1721
RedisMutex.prototype.unlock = function (cb) {
1822
this.redis.del(this.key, cb);
19-
};
23+
};

unit/redis-mutex.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
var Lab = require('lab');
2+
var describe = Lab.experiment;
3+
var it = Lab.test;
4+
var expect = Lab.expect;
5+
var before = Lab.before;
6+
var after = Lab.after;
7+
var createCount = require('callback-count');
8+
var redisCleaner = require('../test/fixtures/redis-cleaner');
9+
var RedisMutex = require('models/redis/mutex');
10+
11+
12+
describe('RedisMutex', function () {
13+
before(redisCleaner.clean('*'));
14+
after(redisCleaner.clean('*'));
15+
16+
var ctx = {};
17+
18+
describe('lock', function () {
19+
20+
it('should lock', function (done) {
21+
var mutex = new RedisMutex('key-1');
22+
mutex.lock(function (err, success) {
23+
if (err) { return done(err); }
24+
expect(success).to.equal(true);
25+
done();
26+
});
27+
});
28+
29+
it('should fail to lock with the same key', function (done) {
30+
var mutex = new RedisMutex('key-1');
31+
mutex.lock(function (err, success) {
32+
if (err) { return done(err); }
33+
expect(success).to.equal(false);
34+
done();
35+
});
36+
});
37+
38+
describe('unlock', function () {
39+
40+
it('should be able to lock after unlock', function (done) {
41+
var mutex = new RedisMutex('key-1');
42+
mutex.unlock(function (err, success) {
43+
if (err) { return done(err); }
44+
expect(success).to.equal('1');
45+
mutex.lock(function (err, success) {
46+
if (err) { return done(err); }
47+
expect(success).to.equal(true);
48+
done();
49+
});
50+
});
51+
});
52+
53+
});
54+
55+
56+
describe('ttl', function () {
57+
before(function (done) {
58+
ctx.originREDIS_LOCK_EXPIRES = process.env.REDIS_LOCK_EXPIRES;
59+
done();
60+
});
61+
after(function (done) {
62+
process.env.REDIS_LOCK_EXPIRES = ctx.originREDIS_LOCK_EXPIRES;
63+
done();
64+
});
65+
66+
it('should release lock after expiration time', function (done) {
67+
var count = createCount(2, done);
68+
process.env.REDIS_LOCK_EXPIRES = 50;
69+
var mutex1 = new RedisMutex('new-key-1');
70+
var mutex2 = new RedisMutex('new-key-1');
71+
setTimeout(function () {
72+
mutex2.lock(function (err, success) {
73+
if (err) { return done(err); }
74+
expect(success).to.equal(true);
75+
count.next();
76+
});
77+
}, 100);
78+
mutex1.lock(function (err, success) {
79+
if (err) { return done(err); }
80+
expect(success).to.equal(true);
81+
mutex2.lock(function (err, success) {
82+
if (err) { return done(err); }
83+
expect(success).to.equal(false);
84+
count.next();
85+
});
86+
});
87+
});
88+
});
89+
90+
});
91+
92+
93+
});

0 commit comments

Comments
 (0)