Comparing version
@@ -0,1 +1,13 @@ | ||
v0.2.5 | ||
====== | ||
- [upgrade] Upgraded node redis to version 0.12.x | ||
- [improvement] eslinted all code. | ||
- [fix] added missing token when calling takeLock on jobs. | ||
[Changes](https://github.com/OptimalBits/bull/compare/v0.2.4...v0.2.5) | ||
v0.2.4 | ||
====== | ||
[Changes](https://github.com/OptimalBits/bull/compare/v0.2.3...v0.2.4) | ||
v0.2.3 | ||
@@ -21,5 +33,4 @@ ====== | ||
====== | ||
- [Fix] Improved and corrected job's getters. | ||
- [Fix] Automatically restart queues in the event of redis disconnections. | ||
- [Feature] Added support for adding jobs in a LIFO fashion. |
@@ -1,3 +0,5 @@ | ||
"use strict"; | ||
var redis = require('redis'); | ||
/*eslint-env node */ | ||
/*global Promise:true */ | ||
'use strict'; | ||
var Promise = require('bluebird'); | ||
@@ -25,3 +27,3 @@ var _ = require('lodash'); | ||
this.stacktrace = null; | ||
} | ||
}; | ||
@@ -33,3 +35,3 @@ Job.create = function(queue, jobId, data, opts){ | ||
}); | ||
} | ||
}; | ||
@@ -44,3 +46,3 @@ Job.fromId = function(queue, jobId){ | ||
}); | ||
} | ||
}; | ||
@@ -54,4 +56,4 @@ Job.prototype.toData = function(){ | ||
timestamp: this.timestamp | ||
} | ||
} | ||
}; | ||
}; | ||
@@ -67,3 +69,3 @@ Job.prototype.progress = function(progress){ | ||
} | ||
} | ||
}; | ||
@@ -74,4 +76,4 @@ /** | ||
Job.prototype.lockKey = function(){ | ||
return this.queue.toKey(this.jobId)+':lock'; | ||
} | ||
return this.queue.toKey(this.jobId) + ':lock'; | ||
}; | ||
@@ -91,3 +93,3 @@ /** | ||
}); | ||
} | ||
}; | ||
@@ -99,3 +101,3 @@ /** | ||
return this.takeLock(token, true); | ||
} | ||
}; | ||
@@ -117,3 +119,3 @@ /** | ||
}); | ||
} | ||
}; | ||
@@ -131,7 +133,7 @@ Job.prototype.delayIfNeeded = function(){ | ||
return Promise.resolve(false); | ||
} | ||
}; | ||
Job.prototype.moveToCompleted = function(){ | ||
return this._moveToSet('completed'); | ||
} | ||
}; | ||
@@ -142,9 +144,9 @@ Job.prototype.moveToFailed = function(err){ | ||
_this.stacktrace = err.stack; | ||
return _this.queue.client.hset(_this.queue.toKey(_this.jobId), 'stacktrace', err.stack); | ||
return _this.queue.client.hsetAsync(_this.queue.toKey(_this.jobId), 'stacktrace', err.stack); | ||
}); | ||
} | ||
}; | ||
Job.prototype.moveToDelayed = function(timestamp){ | ||
return this._moveToSet('delayed', timestamp); | ||
} | ||
return this._moveToSet('delayed', timestamp); | ||
}; | ||
@@ -167,11 +169,11 @@ Job.prototype.retry = function(){ | ||
}); | ||
} | ||
}; | ||
Job.prototype.isCompleted = function(){ | ||
return this._isDone('completed'); | ||
} | ||
}; | ||
Job.prototype.isFailed = function(){ | ||
return this._isDone('failed'); | ||
} | ||
}; | ||
@@ -204,3 +206,4 @@ /** | ||
return queue.toKey(name); | ||
}); | ||
} | ||
); | ||
@@ -221,3 +224,3 @@ var job = this; | ||
}); | ||
} | ||
}; | ||
@@ -232,5 +235,4 @@ // ----------------------------------------------------------------------------- | ||
}); | ||
} | ||
}; | ||
Job.prototype._moveToSet = function(set, delayTimestamp){ | ||
@@ -240,3 +242,3 @@ var queue = this.queue; | ||
delayTimestamp = +delayTimestamp || 0; | ||
delayTimestamp = +delayTimestamp || 0; | ||
delayTimestamp = delayTimestamp < 0 ? 0 : delayTimestamp; | ||
@@ -264,3 +266,4 @@ | ||
return queue.toKey(name); | ||
}); | ||
} | ||
); | ||
@@ -276,6 +279,6 @@ return queue.client.evalAsync( | ||
if(result === -1){ | ||
throw Error("Missing Job " + jobId + " when trying to move from active to "+set); | ||
throw new Error('Missing Job ' + jobId + ' when trying to move from active to ' + set); | ||
} | ||
}); | ||
} | ||
}; | ||
@@ -292,4 +295,4 @@ | ||
return job; | ||
} | ||
}; | ||
module.exports = Job; |
134
lib/queue.js
@@ -1,2 +0,5 @@ | ||
"use strict"; | ||
/*eslint-env node */ | ||
/*global Promise:true */ | ||
'use strict'; | ||
var redis = require('redis'); | ||
@@ -47,3 +50,3 @@ var events = require('events'); | ||
var Queue = function Queue(name, redisPort, redisHost, redisOptions){ | ||
if (!(this instanceof Queue)) { | ||
if(!(this instanceof Queue)){ | ||
return new Queue(name, redisPort, redisHost, redisOptions); | ||
@@ -56,4 +59,4 @@ } | ||
var redisOpts = opts.redis || {}; | ||
redisPort = redisOpts.port || 6379; | ||
redisHost = redisOpts.host || '127.0.0.1'; | ||
redisPort = redisOpts.port; | ||
redisHost = redisOpts.host; | ||
redisOptions = redisOpts.opts || {}; | ||
@@ -63,2 +66,5 @@ redisDB = redisOpts.DB || redisDB; | ||
redisPort = redisPort || 6379; | ||
redisHost = redisHost || '127.0.0.1'; | ||
var _this = this; | ||
@@ -75,3 +81,3 @@ | ||
if(semver.lt(version, MINIMUM_REDIS_VERSION)){ | ||
throw Error("Redis version needs to be greater than "+MINIMUM_REDIS_VERSION+". Current: "+version); | ||
throw new Error('Redis version needs to be greater than ' + MINIMUM_REDIS_VERSION + '. Current: ' + version); | ||
} | ||
@@ -93,3 +99,3 @@ }).catch(function(err){ | ||
this.delayedTimestamp = Number.MAX_VALUE; | ||
this.delayTimer; | ||
this.delayTimer = null; | ||
this.processing = 0; | ||
@@ -121,6 +127,6 @@ | ||
_this.updateDelayTimer(message); | ||
}else if(channel = _this.toKey('paused')){ | ||
if(message == 'paused'){ | ||
}else if(channel === _this.toKey('paused')){ | ||
if(message === 'paused'){ | ||
_this.emit('paused'); | ||
}else if(message == 'resumed'){ | ||
}else if(message === 'resumed'){ | ||
_this.emit('resumed'); | ||
@@ -130,3 +136,3 @@ } | ||
}); | ||
} | ||
}; | ||
@@ -139,3 +145,3 @@ util.inherits(Queue, events.EventEmitter); | ||
return new Promise(function(resolve, reject) { | ||
return new Promise(function(resolve) { | ||
var triggerEvent = _.after(3, resolve); | ||
@@ -149,3 +155,3 @@ _this.client.end(); | ||
}).timeout(CLIENT_CLOSE_TIMEOUT_MS, timeoutMsg); | ||
} | ||
}; | ||
@@ -160,3 +166,3 @@ /** | ||
if (typeof concurrency == "function") { | ||
if(typeof concurrency === 'function'){ | ||
handler = concurrency; | ||
@@ -166,3 +172,3 @@ concurrency = 1; | ||
if(this.handler) { | ||
throw Error("Cannot define a handler more than once per Queue instance"); | ||
throw new Error('Cannot define a handler more than once per Queue instance'); | ||
} | ||
@@ -221,3 +227,3 @@ | ||
}); | ||
} | ||
}; | ||
@@ -232,11 +238,11 @@ // | ||
'if redis.call("EXISTS", KEYS[3]) ~= 1 then', | ||
' redis.call("'+ push + '", KEYS[1], ARGV[1])', | ||
' redis.call("' + push + '", KEYS[1], ARGV[1])', | ||
'else', | ||
' redis.call("'+ push + '", KEYS[2], ARGV[1])', | ||
' redis.call("' + push + '", KEYS[2], ARGV[1])', | ||
'end', | ||
'redis.call("PUBLISH", KEYS[4], ARGV[1])', | ||
'redis.call("PUBLISH", KEYS[4], ARGV[1])' | ||
].join('\n'); | ||
var keys = _.map(['wait', 'paused', 'meta-paused', 'jobs'], function(name){ | ||
return queue.toKey(name); | ||
return queue.toKey(name); | ||
}); | ||
@@ -259,3 +265,3 @@ | ||
}); | ||
} | ||
}; | ||
@@ -290,3 +296,3 @@ /** | ||
if(jobKeys.length){ | ||
var multi = _this.multi(); | ||
multi = _this.multi(); | ||
@@ -297,3 +303,3 @@ multi.del.apply(multi, jobKeys); | ||
}); | ||
} | ||
}; | ||
@@ -313,7 +319,7 @@ /** | ||
return pauseResume(this, true); | ||
} | ||
}; | ||
Queue.prototype.resume = function(){ | ||
return pauseResume(this, false); | ||
} | ||
return pauseResume(this, false); | ||
}; | ||
@@ -336,10 +342,10 @@ function pauseResume(queue, pause){ | ||
'end', | ||
'redis.call("PUBLISH", KEYS[4], ARGV[1])', | ||
'redis.call("PUBLISH", KEYS[4], ARGV[1])' | ||
].join('\n'); | ||
var keys = _.map([src, dst, 'meta-paused', 'paused'], function(name){ | ||
return queue.toKey(name); | ||
return queue.toKey(name); | ||
}); | ||
return queue.client.evalAsync(script, keys.length, keys[0], keys[1], keys[2], keys[3], pause ? "paused" : "resumed"); | ||
return queue.client.evalAsync(script, keys.length, keys[0], keys[1], keys[2], keys[3], pause ? 'paused' : 'resumed'); | ||
} | ||
@@ -352,7 +358,7 @@ | ||
while(i--) { | ||
promises.push(this.processStalledJobs().then(this.processJobs.bind(this))) | ||
promises.push(this.processStalledJobs().then(this.processJobs.bind(this))); | ||
} | ||
return Promise.all(promises); | ||
} | ||
}; | ||
@@ -379,3 +385,3 @@ // --------------------------------------------------------------------- | ||
updateDelaySet(_this, _this.delayedTimestamp).catch(function(err){ | ||
console.log("Error updating delay timer", err); | ||
console.log('Error updating delay timer', err); | ||
}); | ||
@@ -385,3 +391,3 @@ _this.delayedTimestamp = Number.MAX_VALUE; | ||
} | ||
} | ||
}; | ||
@@ -419,3 +425,4 @@ /** | ||
return queue.toKey(name); | ||
}); | ||
} | ||
); | ||
@@ -431,3 +438,3 @@ return queue.client.evalAsync( | ||
delayedTimestamp); | ||
} | ||
}; | ||
@@ -444,3 +451,3 @@ /** | ||
return Job.fromId(_this, jobId); | ||
})) | ||
})); | ||
}).then(function(jobs){ | ||
@@ -452,3 +459,3 @@ var tasks = jobs.map(function(job){ | ||
}); | ||
} | ||
}; | ||
@@ -471,3 +478,3 @@ Queue.prototype.processStalledJob = function(job){ | ||
} | ||
} | ||
}; | ||
@@ -479,5 +486,5 @@ Queue.prototype.processJobs = function(){ | ||
return job.delayIfNeeded().then(function(delayed) { | ||
return !delayed && job.takeLock(); | ||
return !delayed && job.takeLock(_this.token); | ||
}).then(function (locked) { | ||
if (locked) { | ||
if(locked){ | ||
return _this.processJob(job); | ||
@@ -489,3 +496,3 @@ } | ||
}); | ||
} | ||
}; | ||
@@ -498,3 +505,3 @@ Queue.prototype.processJob = function(job){ | ||
job.renewLock(_this.token); | ||
lockRenewTimeout = setTimeout(lockRenewer, _this.LOCK_RENEW_TIME/2); | ||
lockRenewTimeout = setTimeout(lockRenewer, _this.LOCK_RENEW_TIME / 2); | ||
}; | ||
@@ -504,3 +511,2 @@ var runHandler = Promise.promisify(this.handler.bind(this)); | ||
function finishProcessing(){ | ||
@@ -515,3 +521,3 @@ clearTimeout(lockRenewTimeout); | ||
return job.moveToCompleted().then(function(){ | ||
_this.emit('completed', job, data); | ||
_this.emit('completed', job, data); | ||
}); | ||
@@ -526,3 +532,3 @@ } | ||
.then(function(){ | ||
_this.emit('failed', job, error); | ||
_this.emit('failed', job, error); | ||
}); | ||
@@ -542,3 +548,3 @@ } | ||
return jobPromise.then(handleCompleted, handleFailed).finally(finishProcessing); | ||
} | ||
}; | ||
@@ -552,3 +558,3 @@ /** | ||
return this.moveJob('wait', 'active', opts).then(getJobFromId); | ||
} | ||
}; | ||
@@ -559,3 +565,3 @@ Queue.prototype.multi = function(){ | ||
return multi; | ||
} | ||
}; | ||
@@ -568,32 +574,32 @@ /** | ||
Queue.prototype.moveJob = function(src, dst, opts) { | ||
if (opts && opts.block == false) { | ||
if(opts && opts.block === false){ | ||
return this.bclient.rpoplpushAsync(this.toKey(src), this.toKey(dst)); | ||
} else { | ||
}else{ | ||
return this.bclient.brpoplpushAsync(this.toKey(src), this.toKey(dst), 0); | ||
} | ||
} | ||
}; | ||
Queue.prototype.getJob = function(jobId){ | ||
return Job.fromId(this, jobId); | ||
} | ||
}; | ||
Queue.prototype.getWaiting = function(start, end){ | ||
Queue.prototype.getWaiting = function(/*start, end*/){ | ||
return this.getJobs('wait', 'LIST'); | ||
} | ||
}; | ||
Queue.prototype.getActive = function(start, end){ | ||
Queue.prototype.getActive = function(/*start, end*/){ | ||
return this.getJobs('active', 'LIST'); | ||
} | ||
}; | ||
Queue.prototype.getDelayed = function(start, end){ | ||
Queue.prototype.getDelayed = function(/*start, end*/){ | ||
return this.getJobs('delayed', 'ZSET'); | ||
} | ||
}; | ||
Queue.prototype.getCompleted = function(){ | ||
return this.getJobs('completed', 'SET'); | ||
} | ||
}; | ||
Queue.prototype.getFailed = function(){ | ||
return this.getJobs('failed', 'SET'); | ||
} | ||
}; | ||
@@ -624,11 +630,11 @@ Queue.prototype.getJobs = function(queueType, type, start, end){ | ||
}); | ||
} | ||
}; | ||
Queue.prototype.retryJob = function(job) { | ||
return job.retry(); | ||
} | ||
}; | ||
Queue.prototype.toKey = function(queueType){ | ||
return 'bull:' + this.name + ':' + queueType; | ||
} | ||
}; | ||
@@ -643,3 +649,3 @@ | ||
var lines = doc.split('\r\n'); | ||
for(var i=0; i<lines.length; i++){ | ||
for(var i = 0; i < lines.length; i++){ | ||
if(lines[i].indexOf(prefix) === 0){ | ||
@@ -650,4 +656,4 @@ return lines[i].substr(prefix.length); | ||
}); | ||
} | ||
}; | ||
module.exports = Queue; |
{ | ||
"name": "bull", | ||
"version": "0.2.4", | ||
"version": "0.2.5", | ||
"description": "Job manager", | ||
@@ -23,3 +23,3 @@ "main": "index.js", | ||
"node-uuid": "~1.4.1", | ||
"redis": "~0.8.4", | ||
"redis": "^0.12.1", | ||
"semver": "^4.2.0", | ||
@@ -30,4 +30,6 @@ "when": "~2.1.1" | ||
"expect.js": "~0.2.0", | ||
"sinon": "~1.12.1", | ||
"mocha": "~1.21.4" | ||
"gulp": "^3.8.11", | ||
"gulp-eslint": "^0.7.0", | ||
"mocha": "~1.21.4", | ||
"sinon": "~1.12.1" | ||
}, | ||
@@ -34,0 +36,0 @@ "scripts": { |
@@ -6,3 +6,3 @@ var Job = require('../lib/job'); | ||
describe.only('Job', function(){ | ||
describe('Job', function(){ | ||
var queue; | ||
@@ -97,3 +97,3 @@ | ||
describe('Locking', function(){ | ||
var id = 0; | ||
var id = 1000; | ||
var job; | ||
@@ -110,4 +110,8 @@ | ||
it('can take a lock', function(){ | ||
return job.takeLock('123').then(function(lockTaken){ | ||
return job.takeLock('423').then(function(lockTaken){ | ||
expect(lockTaken).to.be(true); | ||
}).then(function(){ | ||
return job.releaseLock('321').then(function(lockReleased){ | ||
expect(lockReleased).to.be(false); | ||
}); | ||
}); | ||
@@ -114,0 +118,0 @@ }); |
@@ -75,7 +75,7 @@ "use strict"; | ||
queue.once('ready', function(){ | ||
expect(queue.client.host).to.be('127.0.0.1'); | ||
expect(queue.bclient.host).to.be('127.0.0.1'); | ||
expect(queue.client.connectionOption.host).to.be('127.0.0.1'); | ||
expect(queue.bclient.connectionOption.host).to.be('127.0.0.1'); | ||
expect(queue.client.port).to.be(6379); | ||
expect(queue.bclient.port).to.be(6379); | ||
expect(queue.client.connectionOption.port).to.be(6379); | ||
expect(queue.bclient.connectionOption.port).to.be(6379); | ||
@@ -93,7 +93,7 @@ expect(queue.client.selected_db).to.be(0); | ||
queue.once('ready', function(){ | ||
expect(queue.client.host).to.be('127.0.0.1'); | ||
expect(queue.bclient.host).to.be('127.0.0.1'); | ||
expect(queue.client.connectionOption.host).to.be('127.0.0.1'); | ||
expect(queue.bclient.connectionOption.host).to.be('127.0.0.1'); | ||
expect(queue.client.port).to.be(6379); | ||
expect(queue.bclient.port).to.be(6379); | ||
expect(queue.client.connectionOption.port).to.be(6379); | ||
expect(queue.bclient.connectionOption.port).to.be(6379); | ||
@@ -111,4 +111,4 @@ expect(queue.client.selected_db).to.be(1); | ||
queue.once('ready', function(){ | ||
expect(queue.client.host).to.be('localhost'); | ||
expect(queue.bclient.host).to.be('localhost'); | ||
expect(queue.client.connectionOption.host).to.be('localhost'); | ||
expect(queue.bclient.connectionOption.host).to.be('localhost'); | ||
@@ -115,0 +115,0 @@ expect(queue.client.selected_db).to.be(0); |
98074
1.97%20
5.26%2599
1.88%5
66.67%+ Added
- Removed
Updated