Skip to content

Commit

Permalink
Refactor code and also fix issue with "unlock" event.
Browse files Browse the repository at this point in the history
Fix #6
  • Loading branch information
gregberge committed Jan 29, 2015
1 parent 776e0e1 commit 6171578
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 23 deletions.
49 changes: 34 additions & 15 deletions lib/locky.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
var events = require('events');
var util = require('util');
var _ = require('lodash');
var resourceKey = require('./resource-key');
var redis = require('then-redis');
var Promise = require('bluebird');
var pipeEvent = require('pipe-event');
var resourceKey = require('./resource-key');

/**
* Expose module.
Expand All @@ -34,9 +35,9 @@ function Locky(options) {
locky.ttl = options.ttl;
locky.redis = locky._createRedisClient(options.redis);

this.redis.on('error', function (err) {
console.log(err);
});
pipeEvent(['error'], locky.redis, this);

locky._resourceTimeouts = {};

events.EventEmitter.call(locky);
}
Expand All @@ -57,7 +58,7 @@ util.inherits(Locky, events.EventEmitter);
* @param {Promise} [callback] Optional callback
*/

Locky.prototype.lock = function lock(options, callback) {
Locky.prototype.lock = function (options, callback) {
var locky = this;

options = options || {};
Expand All @@ -68,7 +69,7 @@ Locky.prototype.lock = function lock(options, callback) {
// Define the method to use.
var method = options.force ? 'set' : 'setnx';

// Set the lock key.
// Set the lock key.
return locky.redis[method](key, options.locker)
.then(function (res) {
var success = res === 1 || res === 'OK';
Expand Down Expand Up @@ -96,7 +97,7 @@ Locky.prototype.lock = function lock(options, callback) {
* @param {function} [callback] Optional callback
*/

Locky.prototype.refresh = function refresh(resource, callback) {
Locky.prototype.refresh = function (resource, callback) {
var locky = this;

return new Promise(function (resolve, reject) {
Expand All @@ -122,15 +123,19 @@ Locky.prototype.refresh = function refresh(resource, callback) {
* @param {function} [callback] Optional callback
*/

Locky.prototype.unlock = function unlock(resource, callback) {
Locky.prototype.unlock = function (resource, callback) {
var locky = this;

// Format key with resource id.
var key = resourceKey.format(resource);

// Remove the key.
return locky.redis.del(key).then(function (res) {
if (res !== 0) locky.emit('unlock', resource);
return locky.redis.del(key)
.then(function (res) {
if (res === 0) return;

locky.emit('unlock', resource);
locky._clearExpiration(resource);
})
.nodeify(callback);
};
Expand All @@ -142,7 +147,7 @@ Locky.prototype.unlock = function unlock(resource, callback) {
* @param {function} [callback] Optional callback
*/

Locky.prototype.getLocker = function getLocker(resource, callback) {
Locky.prototype.getLocker = function (resource, callback) {
return this.redis.get(resourceKey.format(resource)).nodeify(callback);
};

Expand All @@ -152,7 +157,7 @@ Locky.prototype.getLocker = function getLocker(resource, callback) {
* @param {function} [callback] Optional callback
*/

Locky.prototype.close = function close(callback) {
Locky.prototype.close = function (callback) {
return this.redis.quit().nodeify(callback);
};

Expand All @@ -162,8 +167,22 @@ Locky.prototype.close = function close(callback) {
* @param {string} resource Resource
*/

Locky.prototype._listenExpiration = function _listenExpiration(resource) {
setTimeout(this._onExpire.bind(this, resource), this.ttl);
Locky.prototype._listenExpiration = function (resource) {
var bindedExpire = this._onExpire.bind(this, resource);
this._resourceTimeouts[resource] = setTimeout(bindedExpire, this.ttl);
};

/**
* Clear timeout on expiration.
*
* @param {string} resource Resource
*/

Locky.prototype._clearExpiration = function (resource) {
var timeout = this._resourceTimeouts[resource];

if (timeout)
clearTimeout(timeout);
};

/**
Expand All @@ -172,7 +191,7 @@ Locky.prototype._listenExpiration = function _listenExpiration(resource) {
* @param {string} resource
*/

Locky.prototype._onExpire = function _onExpire(resource) {
Locky.prototype._onExpire = function (resource) {
var locky = this;

return locky.getLocker(resource).then(function (locker) {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"dependencies": {
"bluebird": "^2.9.3",
"lodash": "^3.0.0",
"pipe-event": "^0.1.0",
"redis": "^0.12.1",
"then-redis": "^1.3.0"
}
Expand Down
32 changes: 24 additions & 8 deletions test/locky.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,16 @@ describe('Locky', function () {
});

it('should emit an expire event when the lock expire', function () {
this.timeout(3000);

var spy = sinon.spy();
locky = createLocky({ttl: 1000});
locky = createLocky({ttl: 100});
locky.on('expire', spy);

return locky.lock({
resource: 'article4',
locker: 'john'
})
.then(function () {
return Promise.delay(2100);
return Promise.delay(200);
})
.then(function () {
expect(spy).to.be.calledWith('article4');
Expand Down Expand Up @@ -182,10 +180,8 @@ describe('Locky', function () {
});

it('should emit an expire event when the lock expire', function () {
this.timeout(3000);

var spy = sinon.spy();
locky = createLocky({ttl: 1000});
locky = createLocky({ttl: 100});
locky.on('expire', spy);

locky.redis.multi();
Expand All @@ -194,7 +190,7 @@ describe('Locky', function () {
return locky.redis.exec()
.then(function () {
locky.refresh('article8');
return Promise.delay(2100);
return Promise.delay(200);
})
.then(function () {
expect(spy).to.be.calledWith('article8');
Expand Down Expand Up @@ -241,6 +237,26 @@ describe('Locky', function () {
expect(spy).to.not.be.called;
});
});

it('should not expire if we "unlock"', function () {
var spy = sinon.spy();
locky = createLocky({ttl: 100});
locky.on('expire', spy);

return locky.lock({
resource: 'article13',
locker: 'john'
})
.then(function () {
return locky.unlock('article13');
})
.then(function () {
return Promise.delay(200);
})
.then(function () {
expect(spy).to.not.be.called;
});
});
});

describe('#getLocker', function () {
Expand Down

0 comments on commit 6171578

Please sign in to comment.