UNPKG

node-resque

Version:

an opinionated implementation of resque in node

231 lines (191 loc) 7.06 kB
var specHelper = require(__dirname + "/../_specHelper.js").specHelper; var should = require('should'); describe('worker', function(){ var os = require('os'); var worker; var queue; var jobs = { "add": { perform: function(a,b,callback){ var answer = a + b; callback(null, answer); } }, "badAdd": { perform: function(a,b,callback){ callback(new Error("Blue Smoke")); } }, "doubleCaller":{ perform: function(callback){ callback(null, 'a'); setTimeout(function(){ callback(null, 'b'); }, 500); setTimeout(function(){ callback(null, 'c'); }, 1000); } }, "quickDefine": function(callback) { setTimeout(callback.bind(null, null, "ok")); }, }; it("can connect", function(done){ worker = new specHelper.NR.worker({connection: specHelper.connectionDetails, timeout: specHelper.timeout}, jobs, function(){ should.exist(worker); worker.end(); done(); }); }); it("can provide an error if connection failed", function(done) { // Only run this test if this is using real redis if(process.env.FAKEREDIS == 'true') { return done(); } // Make a copy of the connectionDetails so we don't overwrite the original one var connectionDetails = { package: specHelper.connectionDetails.package, host: "wronghostname", password: specHelper.connectionDetails.password, port: "wrongport", database: specHelper.connectionDetails.database, namespace: specHelper.connectionDetails.namespace, }; resolved = false; worker = new specHelper.NR.worker({connection: connectionDetails, timeout: specHelper.timeout}, jobs, function(err){ if(resolved === false){ // new versions of redis will keep retrying in node v0.11x... should.exist(err); resolved = true; done(); } }); }); describe('[with connection]', function() { before(function(done){ specHelper.connect(function(){ queue = new specHelper.NR.queue({connection: specHelper.connectionDetails, queue: specHelper.queue}, function(){ done(); }); }); }); after(function(done){ specHelper.cleanup(function(){ done(); }); }); it("can boot and stop", function(done){ this.timeout(specHelper.timeout * 3); worker.start(); worker.end(function(){ done(); }); }); describe('crashing workers', function(){ it('can clear previously crashed workers from the same host', function(done){ var name1 = os.hostname() + ":" + "0"; // fake pid var name2 = os.hostname() + ":" + process.pid; // real pid var worker1 = new specHelper.NR.worker({connection: specHelper.connectionDetails, timeout: specHelper.timeout, name: name1}, jobs, function(){ worker1.init(function(){ worker1.running = false; setTimeout(function(){ var worker2 = new specHelper.NR.worker({connection: specHelper.connectionDetails, timeout: specHelper.timeout, name: name2}, jobs, function(){ worker2.on('cleaning_worker', function(worker, pid){ worker.should.equal(name1 + ":*"); pid.should.equal(0); done(); }); worker2.workerCleanup(); }); }, 500); }); }); }); }); describe('integration', function(){ beforeEach(function(done){ worker = new specHelper.NR.worker({connection: specHelper.connectionDetails, timeout: specHelper.timeout, queues: specHelper.queue}, jobs, function(){ done(); }); }); afterEach(function(done){ worker.end(function(){ done(); }); }); it("will mark a job as failed", function(done){ var listener = worker.on('failure', function(q, job, failire){ q.should.equal(specHelper.queue); job.class.should.equal('badAdd'); failire.message.should.equal('Blue Smoke'); worker.removeAllListeners('failire'); done(); }); queue.enqueue(specHelper.queue, "badAdd", [1,2]); worker.start(); }); it('can work a job and return succesful things', function(done){ var listener = worker.on('success', function(q, job, result){ q.should.equal(specHelper.queue); job.class.should.equal('add'); result.should.equal(3); worker.removeAllListeners('success'); done(); }); queue.enqueue(specHelper.queue, "add", [1,2]); worker.start(); }); it('can accept jobs that are simple functions', function(done){ var listener = worker.on('success', function(q, job, result){ result.should.equal("ok"); worker.removeAllListeners('success'); done(); }); queue.enqueue(specHelper.queue, "quickDefine", []); worker.start(); }); it('will not work jobs that are not defined', function(done){ var listener = worker.on('failure', function(q, job, failure){ q.should.equal(specHelper.queue); String(failure).should.equal == "Error: No job defined for class 'somethingFake'"; worker.removeAllListeners('failure'); done(); }); queue.enqueue(specHelper.queue, "somethingFake", []); worker.start(); }); it('will place failed jobs in the failed queue', function(done){ specHelper.redis.rpop(specHelper.namespace + ":" + "failed", function(err, data){ data = JSON.parse(data); data.queue.should.equal(specHelper.queue); data.exception.should.equal('Error'); data.error.should.equal('No job defined for class \'somethingFake\''); done(); }); }); it('will not double-work with a baddly defined job', function(done){ var callbackCounts = 0; var expected = 3; var errorCounter = 0; var successCounter = 0; var errorListener = worker.on('failure', function(q, job, err){ String(err).should.equal('Error: refusing to continue with job, multiple callbacks detected'); callbackCounts++; errorCounter++; if(callbackCounts === expected){ complete(); } }); var successListener = worker.on('success', function(q, job, result){ result.should.equal('a'); successCounter++; callbackCounts++; if(callbackCounts === expected){ complete(); } }); var complete = function(){ errorCounter.should.equal(2); successCounter.should.equal(1); worker.removeAllListeners('success'); worker.removeAllListeners('failure'); done(); }; queue.enqueue(specHelper.queue, "doubleCaller", []); worker.start(); }); }); }); });