Comparing version 0.1.3 to 0.1.4
@@ -220,5 +220,7 @@ | ||
.then(function() { | ||
// handle shutdown state | ||
if (self.shutdown) { | ||
self.shutdown = false; | ||
self.emit('queue stop'); | ||
// loop | ||
} else { | ||
@@ -239,5 +241,9 @@ return self.run(); | ||
var self = this; | ||
// blocking timeout, try again | ||
if (res === this.status_timeout) { | ||
return this.nextJob(); | ||
return this.nextJob().then(function(res) { | ||
return self.handleStatus(res); | ||
}); | ||
@@ -275,33 +281,5 @@ // pass on result | ||
// job done, remove it | ||
return new Promise(function(resolve, reject) { | ||
self.client.multi() | ||
.lrem(self.runQueue, 1, job.id) | ||
.del(self.prefix + ':' + job.id) | ||
.exec(function(err, res) { | ||
// client error | ||
if (err) { | ||
// only return the first error | ||
if (err.length > 0) { | ||
err = err[0]; | ||
} | ||
reject(err); | ||
// see Queue.prototype.add comments on why these check are necessary | ||
} else if (res[0] != 1) { | ||
err = new Error('unable to remove job id'); | ||
reject(err); | ||
} else if (res[1] != 1) { | ||
err = new Error('unable to remove job data'); | ||
reject(err); | ||
} else { | ||
// job done event | ||
self.emit('queue ok', job); | ||
resolve(); | ||
} | ||
}); | ||
// job done, remove it and emit event | ||
return this.remove(job.id).then(function() { | ||
self.emit('queue ok', job); | ||
}); | ||
@@ -321,3 +299,2 @@ | ||
// job done, remove it | ||
return new Promise(function(resolve, reject) { | ||
@@ -367,2 +344,45 @@ | ||
/** | ||
* Remove a job from queue given the job id | ||
* | ||
* @param Number id Job id | ||
* @return Promise | ||
*/ | ||
Queue.prototype.remove = function(id) { | ||
var self = this; | ||
// job done, remove it | ||
return new Promise(function(resolve, reject) { | ||
self.client.multi() | ||
.lrem(self.runQueue, 1, id) | ||
.del(self.prefix + ':' + id) | ||
.exec(function(err, res) { | ||
// client error | ||
if (err) { | ||
// only return the first error | ||
if (err.length > 0) { | ||
err = err[0]; | ||
} | ||
reject(err); | ||
// see Queue.prototype.add comments on why these check are necessary | ||
} else if (res[0] != 1) { | ||
err = new Error('unable to remove job id'); | ||
reject(err); | ||
} else if (res[1] != 1) { | ||
err = new Error('unable to remove job data'); | ||
reject(err); | ||
} else { | ||
resolve(); | ||
} | ||
}); | ||
}); | ||
}; | ||
/** | ||
* Stop queue processing gracefully | ||
@@ -474,5 +494,2 @@ * | ||
data = data || {}; | ||
opts = opts || {}; | ||
var self = this; | ||
@@ -483,2 +500,8 @@ | ||
if (!data || typeof data !== 'object') { | ||
throw new Error('job data must be an object'); | ||
} | ||
opts = opts || {}; | ||
// job structure | ||
@@ -485,0 +508,0 @@ var job = { |
{ | ||
"name": "decent", | ||
"version": "0.1.3", | ||
"description": "Redis-based job queue for Node: job queue is hard to manage, we make it decent for you.", | ||
"version": "0.1.4", | ||
"description": "This is a decent Redis-based job queue for Node.", | ||
"main": "index.js", | ||
@@ -9,2 +9,3 @@ "scripts": { | ||
"dev": "nodemon ./node_modules/.bin/mocha --harmony test/test.js", | ||
"report": "istanbul cover _mocha -- -R spec test/test.js", | ||
"coverage": "istanbul cover _mocha --report lcovonly -- -R spec test/test.js && cat ./coverage/lcov.info | coveralls" | ||
@@ -36,2 +37,3 @@ }, | ||
"coveralls": "^2.11.2", | ||
"fakeredis": "^0.2.2", | ||
"istanbul": "^0.3.4", | ||
@@ -38,0 +40,0 @@ "mocha": "^2.0.1", |
@@ -5,3 +5,3 @@ | ||
[![npm version](https://badge.fury.io/js/decent.svg)](http://badge.fury.io/js/decent) [![Build Status](https://travis-ci.org/bitinn/decent.svg?branch=master)](https://travis-ci.org/bitinn/decent) [![Coverage Status](https://img.shields.io/coveralls/bitinn/decent.svg)](https://coveralls.io/r/bitinn/decent) | ||
[![npm version](https://badge.fury.io/js/decent.svg)](http://badge.fury.io/js/decent) [![Build Status](https://travis-ci.org/bitinn/decent.svg?branch=master)](https://travis-ci.org/bitinn/decent) [![Coverage Status](https://img.shields.io/coveralls/bitinn/decent.svg)](https://coveralls.io/r/bitinn/decent) [![Dependency Status](https://david-dm.org/bitinn/decent.svg)](https://david-dm.org/bitinn/decent) | ||
@@ -8,0 +8,0 @@ `decent` is a Redis-based job queue for Node. |
155
test/test.js
@@ -17,2 +17,3 @@ | ||
var Promise = require('native-or-bluebird'); | ||
var Redis = require('fakeredis'); | ||
@@ -149,2 +150,12 @@ // global vars | ||
}); | ||
it('should reject on connection failure', function() { | ||
var p = queue.nextJob(); | ||
setTimeout(function() { | ||
queue.bclient.stream.destroy(); | ||
}, 25); | ||
return expect(p).to.eventually.be.rejectedWith(Error); | ||
}); | ||
}); | ||
@@ -324,8 +335,15 @@ | ||
it('should get next job again if input is status_timeout', function() { | ||
var job = { | ||
id: 1 | ||
, data: { a: 1 } | ||
, retry: 0 | ||
, timeout: 60 | ||
}; | ||
var stub = sinon.stub(queue, 'nextJob'); | ||
stub.returns(Promise.resolve(true)); | ||
stub.returns(Promise.resolve(job)); | ||
return queue.handleStatus(queue.status_timeout).then(function(res) { | ||
expect(stub).to.have.been.calledOnce; | ||
expect(res).to.be.true; | ||
expect(res).to.equal(job); | ||
}); | ||
@@ -456,4 +474,6 @@ }); | ||
}); | ||
}); | ||
it('should remove job if handler ran successfully', function() { | ||
describe('moveJob', function() { | ||
it('should move job into work queue when retry available', function() { | ||
var job = { | ||
@@ -469,7 +489,5 @@ id: 1 | ||
queue.handler = function() {}; | ||
return queue.handleJob(job).then(function() { | ||
return queue.count('run').then(function(count) { | ||
expect(count).to.equal(0); | ||
return queue.moveJob(job).then(function() { | ||
return queue.count('work').then(function(count) { | ||
expect(count).to.equal(1); | ||
}); | ||
@@ -479,18 +497,21 @@ }); | ||
it('should reject if purge command return unexpected result', function() { | ||
it('should move job into fail queue when retry limit reached', function() { | ||
var job = { | ||
id: 1 | ||
, data: { a: 1 } | ||
, retry: 0 | ||
, retry: 3 | ||
, timeout: 60 | ||
}; | ||
queue.handler = function() {}; | ||
queue.client.hmset(queue.prefix + ':' + job.id, queue.toClient(job)); | ||
queue.client.lpush(queue.runQueue, job.id); | ||
return expect(queue.handleJob(job)).to.eventually.be.rejectedWith(Error); | ||
return queue.moveJob(job).then(function() { | ||
return queue.count('fail').then(function(count) { | ||
expect(count).to.equal(1); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('moveJob', function() { | ||
it('should move job into work queue when retry available', function() { | ||
it('should increment job retry count', function() { | ||
var job = { | ||
@@ -507,4 +528,4 @@ id: 1 | ||
return queue.moveJob(job).then(function() { | ||
return queue.count('work').then(function(count) { | ||
expect(count).to.equal(1); | ||
return queue.get(job.id).then(function(job) { | ||
expect(job.retry).to.equal(1); | ||
}); | ||
@@ -514,7 +535,7 @@ }); | ||
it('should move job into fail queue when retry limit reached', function() { | ||
it('should reject on connection failure', function() { | ||
var job = { | ||
id: 1 | ||
, data: { a: 1 } | ||
, retry: 3 | ||
, retry: 0 | ||
, timeout: 60 | ||
@@ -526,10 +547,9 @@ }; | ||
return queue.moveJob(job).then(function() { | ||
return queue.count('fail').then(function(count) { | ||
expect(count).to.equal(1); | ||
}); | ||
}); | ||
var p = queue.moveJob(job); | ||
queue.client.stream.destroy(); | ||
return expect(p).to.eventually.be.rejectedWith(Error); | ||
}); | ||
it('should increment job retry count', function() { | ||
it('should reject if move command return unexpected result', function() { | ||
var job = { | ||
@@ -542,8 +562,22 @@ id: 1 | ||
return expect(queue.moveJob(job)).to.eventually.be.rejectedWith(Error); | ||
}); | ||
}); | ||
describe('remove', function() { | ||
it('should remove job from queue and purge job data', function() { | ||
var job = { | ||
id: 1 | ||
, data: { a: 1 } | ||
, retry: 0 | ||
, timeout: 60 | ||
}; | ||
queue.client.hmset(queue.prefix + ':' + job.id, queue.toClient(job)); | ||
queue.client.lpush(queue.runQueue, job.id); | ||
return queue.moveJob(job).then(function() { | ||
return queue.get(job.id).then(function(job) { | ||
expect(job.retry).to.equal(1); | ||
return queue.remove(job.id).then(function() { | ||
return queue.count('run').then(function(count) { | ||
expect(count).to.equal(0); | ||
return expect(queue.get(job.id)).to.eventually.be.rejectedWith(Error); | ||
}); | ||
@@ -553,3 +587,3 @@ }); | ||
it('should reject if move command return unexpected result', function() { | ||
it('should reject on connection failure', function() { | ||
var job = { | ||
@@ -562,4 +596,21 @@ id: 1 | ||
return expect(queue.moveJob(job)).to.eventually.be.rejectedWith(Error); | ||
queue.client.hmset(queue.prefix + ':' + job.id, queue.toClient(job)); | ||
queue.client.lpush(queue.runQueue, job.id); | ||
var p = queue.remove(job.id); | ||
queue.client.stream.destroy(); | ||
return expect(p).to.eventually.be.rejectedWith(Error); | ||
}); | ||
it('should reject if remove command return unexpected result', function() { | ||
var job = { | ||
id: 1 | ||
, data: { a: 1 } | ||
, retry: 0 | ||
, timeout: 60 | ||
}; | ||
return expect(queue.remove(job.id)).to.eventually.be.rejectedWith(Error); | ||
}); | ||
}); | ||
@@ -599,5 +650,9 @@ | ||
describe('get', function() { | ||
it('should reject if no id given', function() { | ||
return expect(queue.get()).to.eventually.be.rejectedWith(Error); | ||
}); | ||
it('should return the job', function() { | ||
return queue.add({ a: 1 }).then(function() { | ||
return expect(queue.get(1)).to.eventually.be.fulfilled; | ||
return queue.add({ a: 1 }).then(function(job) { | ||
return expect(queue.get(job.id)).to.eventually.be.fulfilled; | ||
}); | ||
@@ -608,3 +663,3 @@ }); | ||
return queue.add({ a: 1 }).then(function(j1) { | ||
return queue.get(1).then(function(j2) { | ||
return queue.get(j1.id).then(function(j2) { | ||
expect(j2.id).to.equal(j1.id); | ||
@@ -618,2 +673,18 @@ expect(j2.data).to.deep.equal(j1.data); | ||
it('should reject on connection failure', function() { | ||
var job = { | ||
id: 1 | ||
, data: { a: 1 } | ||
, retry: 0 | ||
, timeout: 60 | ||
}; | ||
queue.client.hmset(queue.prefix + ':' + job.id, queue.toClient(job)); | ||
var p = queue.get(job.id); | ||
queue.client.stream.destroy(); | ||
return expect(p).to.eventually.be.rejectedWith(Error); | ||
}); | ||
it('should reject if job data is missing', function() { | ||
@@ -638,2 +709,10 @@ return expect(queue.get(1)).to.eventually.be.rejectedWith(Error); | ||
describe('add', function() { | ||
it('should reject empty data', function() { | ||
return expect(queue.add()).to.eventually.be.rejectedWith(Error); | ||
}); | ||
it('should reject non-object data', function() { | ||
return expect(queue.add('invalid')).to.eventually.be.rejectedWith(Error); | ||
}); | ||
it('should add a new job to queue', function() { | ||
@@ -715,2 +794,9 @@ return queue.add({ a: 1 }).then(function(job) { | ||
}); | ||
it('should reject on connection failure', function() { | ||
var p = queue.add({ a: 1 }); | ||
queue.client.stream.destroy(); | ||
return expect(p).to.eventually.be.rejectedWith(Error); | ||
}); | ||
}); | ||
@@ -749,2 +835,5 @@ | ||
var nonerr = 'not a error'; | ||
queue.client.emit('error', nonerr); | ||
expect(spy).to.have.been.calledOnce; | ||
@@ -751,0 +840,0 @@ expect(spy).to.have.been.calledWith(err); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
43743
10
1259
9