UNPKG

better-queue

Version:
489 lines (463 loc) 10.9 kB
var assert = require('assert'); var helper = require('./lib/helper'); var Queue = require('../lib/queue'); describe('Basic Queue', function() { afterEach(helper.destroyQueues); it('should succeed', function (done) { var q = new Queue(function (n, cb) { cb(null, n+1) }, { autoResume: true }) q.on('task_finish', function (taskId, r) { assert.equal(r, 2); done(); }) q.push(1, function (err, r) { assert.equal(r, 2); }) this.q = q; }); it('should fail task if failTaskOnProcessException is true', function (done) { var q = new Queue(function (n, cb) { throw new Error("failed"); }, { autoResume: true }) q.on('task_failed', function (taskId, err) { assert.equal(err.message, "failed"); done(); }) q.push(1) this.q = q; }); it('should emit an error if failTaskOnProcessException is false', function (done) { var q = new Queue(function (n, cb) { throw new Error("failed"); }, { failTaskOnProcessException: false, autoResume: true }) q.on('error', function () { done(); }) q.push(1) this.q = q; }); it('should fail', function (done) { var q = new Queue(function (n, cb) { cb('nope') }, { autoResume: true }) q.on('task_failed', function (taskId, msg) { assert.equal(msg, 'nope'); done(); }) q.push(1, function (err, r) { assert.equal(err, 'nope'); }) this.q = q; }); it('should run fifo', function (done) { var finished = 0; var queued = 0; var q = new Queue(function (num, cb) { cb() }) q.on('task_finish', function () { if (finished >= 3) { done(); } }) q.on('task_queued', function () { queued++; if (queued >= 3) { q.resume(); } }) q.pause(); q.push(1, function (err, r) { assert.equal(finished, 0); finished++; }) q.push(2, function (err, r) { assert.equal(finished, 1); finished++; }) q.push(3, function (err, r) { assert.equal(finished, 2); finished++; }) this.q = q; }) it('should prioritize', function (done) { var q = new Queue(function (num, cb) { cb() }, { priority: function (n, cb) { if (n === 2) return cb(null, 10); if (n === 1) return cb(null, 5); return cb(null, 1); } }) q.pause(); var finished = 0; var queued = 0; q.on('task_queued', function () { queued++; if (queued === 3) { q.resume(); } }) q.push(3, function (err, r) { assert.equal(finished, 2); finished++; }); q.push(2, function (err, r) { assert.equal(finished, 0); finished++; }); q.push(1, function (err, r) { assert.equal(finished, 1); finished++; done() }); this.q = q; }) it('should run filo', function (done) { var finished = 0; var queued = 0; var q = new Queue(function (num, cb) { cb(); }, { filo: true }) q.on('task_finish', function () { if (finished >= 3) { done(); } }) q.on('task_queued', function () { queued++; if (queued >= 3) { q.resume(); } }) q.pause(); q.push(1, function (err, r) { assert.equal(finished, 2); finished++; }) q.push(2, function (err, r) { assert.equal(finished, 1); finished++; }) q.push(3, function (err, r) { assert.equal(finished, 0); finished++; }) this.q = q; }) it('should filter before process', function (done) { var q = new Queue(function (n, cb) { cb(null, n) }, { filter: function (n, cb) { cb(null, n === 2 ? false : n); } }) q.push(2, function (err, r) { assert.equal(err, 'input_rejected'); }) q.push(3, function (err, r) { assert.equal(r, 3); done(); }) this.q = q; }) it('should batch delay', function (done) { var batches = 0; var q = new Queue(function (batch, cb) { batches++; if (batches === 1) { assert.equal(batch.length, 2); return cb(); } if (batches === 2) { assert.equal(batch.length, 1); cb(); return done(); } }, { batchSize: 2, batchDelay: 5, failTaskOnProcessException: false }); q.push(1); q.push(2); q.push(3); this.q = q; }) it('should batch 2', function (done) { var finished = 0; var q = new Queue(function (batch, cb) { finished++; assert.equal(batch.length, 1); if (finished >= 2) { done(); } cb(); }, { batchSize: 2, batchDelay: 1, autoResume: true }); q.push(1) .on('queued', function () { setTimeout(function () { q.push(2); }, 2) }) this.q = q; }) it('should drain and empty', function (done) { var emptied = false; var q = new Queue(function (n, cb) { cb() }) q.on('empty', function () { emptied = true; }, { autoResume: true }) q.on('drain', function () { assert.ok(emptied); done(); }); var queued = 0; q.on('task_queued', function () { queued++; if (queued >= 3) { q.resume(); } }) q.pause(); q.push(1) q.push(2) q.push(3) this.q = q; }) it('should drain only once the task is complete', function (done) { var finished_task = false; var q = new Queue(function (n, cb) { finished_task = true; cb(); }, { concurrent: 2 }); q.on('drain', function () { assert.ok(finished_task); done(); }); q.push(1); this.q = q; }); it('should queue 50 things', function (done) { var q = new Queue(function (n, cb) { cb(null, n+1); }) var finished = 0; for (var i = 0; i < 50; i++) { (function (n) { q.push(n, function (err, r) { assert.equal(r, n+1); finished++; if (finished === 50) { done(); } }) })(i) } this.q = q; }); it('should concurrently handle tasks', function (done) { var concurrent = 0; var ok = false; var q = new Queue(function (n, cb) { var wait = function () { if (concurrent === 3) { ok = true; } if (ok) return cb(); setImmediate(function () { wait(); }) } concurrent++; wait(); }, { concurrent: 3 }) var finished = 0; var finish = function () { finished++; if (finished >= 4) { done(); } } q.push(0, finish); q.push(1, finish); q.push(2, finish); q.push(3, finish); this.q = q; }) it('should pause and resume', function (done) { var running = false; var q = new Queue(function (n, cb) { running = true; return { pause: function () { running = false; }, resume: function () { running = true; cb(); done(); } } }) q.pause(); q.push(1) .on('started', function () { setTimeout(function () { assert.ok(running); q.pause(); assert.ok(!running); q.resume(); }, 1) }) assert.ok(!running); q.resume(); this.q = q; }) it('should timeout and fail', function (done) { var tries = 0; var q = new Queue(function (n, cb) { tries++; setTimeout(function () { cb(null, 'done!') }, 3) }, { maxTimeout: 1, maxRetries: 2 }) q.push(1) .on('finish', function (result) { assert.ok(false) }) .on('failed', function (err) { assert.equal(tries, 2); setTimeout(function () { done(); }, 5) }) this.q = q; }) it('should cancel while running and in queue', function (done) { var q = new Queue(function (task, cb) { assert.ok(task.n, 2) setTimeout(function () { q.cancel(1); }, 1) return { cancel: function () { done(); } } }, { id: 'id', merge: function (a,b) { assert.ok(false); } }) q.push({ id: 1, n: 1 }) .on('queued', function () { q.cancel(1, function () { q.push({ id: 1, n: 2 }); }) }); this.q = q; }) it('should stop if precondition fails', function (done) { var retries = 0; var q = new Queue(function (n) { assert.equal(retries, 2); done(); }, { precondition: function (cb) { retries++; cb(null, retries === 2) }, preconditionRetryTimeout: 1 }) q.push(1); this.q = q; }) it('should call cb on throw', function (done) { var called = false; var q = new Queue(function (task, cb) { throw new Error('fail'); }); q.push(1, function (err) { called = true; assert.ok(err); }); q.on('drain', function () { assert.ok(called); done(); }); this.q = q; }) it('should respect batchDelayTimeout', function (done) { var q = new Queue(function (arr) { assert.equal(arr.length, 2); done(); }, { batchSize: 3, batchDelay: Infinity, batchDelayTimeout: 5 }) q.push(1); setTimeout(function () { q.push(2); }, 1) this.q = q; }) it('should merge but not batch until the delay has happened', function (done) { var running = false; var q = new Queue(function (arr) { running = true; }, { autoResume: true, batchSize: 2, batchDelay: Infinity, id: 'id' }) setTimeout(function () { q.push({ id: 'a', x: 1 }); q.push({ id: 'a', x: 2 }); }, 1) setTimeout(function () { assert.ok(!running); done(); }, 10) this.q = q; }) it('merge batches should call all push callbacks', function (done) { var count = 0 function finish() { count++ if (count === 2) done() } var q = new Queue(function (arr, cb) { cb() }, { autoResume: true, batchSize: 2, id: 'id' }) q.push({ id: 'a', x: 1 }, finish) q.push({ id: 'a', x: 2 }, finish) this.q = q; }) it('cancel should not retry', function (done) { var count = 0; var q = new Queue(function (n, cb) { count++; if (count === 2) { q.cancel('a', function () { cb('failed again'); setTimeout(function () { if (count === 2) { done(); } }, 100) }) } else { cb('failed'); } }, { autoResume: true, failTaskOnProcessException: true, maxRetries: Infinity, id: 'id' }) q.push({ id: 'a', x: 1 }); this.q = q; }) })