var makeTest = require('./context') var Bottleneck = require('./bottleneck') var assert = require('assert') describe('Group', function () { var c afterEach(function () { return c.limiter.disconnect(false) }) it('Should create limiters', function (done) { c = makeTest() var group = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100 }) var results = [] var job = function (...result) { results.push(result) return new Promise(function (resolve, reject) { setTimeout(function () { return resolve() }, 50) }) } group.key('A').schedule(job, 1, 2) group.key('A').schedule(job, 3) group.key('A').schedule(job, 4) setTimeout(function () { group.key('B').schedule(job, 5) }, 20) setTimeout(function () { group.key('C').schedule(job, 6) group.key('C').schedule(job, 7) }, 40) group.key('A').submit(function (cb) { c.mustEqual(results, [[1,2], [5], [6], [3], [7], [4]]) cb() done() }, null) }) it('Should set up the limiter IDs (default)', function () { c = makeTest() var group = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100 }) c.mustEqual(group.key('A').id, 'group-key-A') c.mustEqual(group.key('B').id, 'group-key-B') c.mustEqual(group.key('XYZ').id, 'group-key-XYZ') var ids = group.keys().map(function (key) { var limiter = group.key(key) c.mustEqual(limiter._store.timeout, group.timeout) return limiter.id }) c.mustEqual(ids.sort(), ['group-key-A', 'group-key-B', 'group-key-XYZ']) }) it('Should set up the limiter IDs (custom)', function () { c = makeTest() var group = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100, id: 'custom-id' }) c.mustEqual(group.key('A').id, 'custom-id-A') c.mustEqual(group.key('B').id, 'custom-id-B') c.mustEqual(group.key('XYZ').id, 'custom-id-XYZ') var ids = group.keys().map(function (key) { var limiter = group.key(key) c.mustEqual(limiter._store.timeout, group.timeout) return limiter.id }) c.mustEqual(ids.sort(), ['custom-id-A', 'custom-id-B', 'custom-id-XYZ']) }) it('Should pass new limiter to \'created\' event', function () { c = makeTest() var group = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100 }) var keys = [] var ids = [] var promises = [] group.on('created', function (created, key) { keys.push(key) promises.push( created.updateSettings({ id: key }) .then(function (limiter) { ids.push(limiter.id) }) ) }) group.key('A') group.key('B') group.key('A') group.key('B') group.key('B') group.key('BB') group.key('C') group.key('A') return Promise.all(promises) .then(function () { c.mustEqual(keys, ids) return c.limiter.ready() }) }) it('Should pass error on failure', function (done) { var failureMessage = 'SOMETHING BLEW UP!!' c = makeTest() var group = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100 }) c.mustEqual(Object.keys(group.limiters), []) var results = [] var job = function (...result) { results.push(result) return new Promise(function (resolve, reject) { setTimeout(function () { return resolve() }, 50) }) } group.key('A').schedule(job, 1, 2) group.key('A').schedule(job, 3) group.key('A').schedule(job, 4) group.key('B').schedule(() => Promise.reject(new Error(failureMessage))) .catch(function (err) { results.push(['CAUGHT', err.message]) }) setTimeout(function () { group.key('C').schedule(job, 6) group.key('C').schedule(job, 7) }, 40) group.key('A').submit(function (cb) { c.mustEqual(results, [[1,2], ['CAUGHT', failureMessage], [6], [3], [7], [4]]) cb() done() }, null) }) it('Should update its timeout', function () { c = makeTest() var group1 = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100 }) var group2 = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100, timeout: 5000 }) c.mustEqual(group1.timeout, 300000) c.mustEqual(group2.timeout, 5000) var p1 = group1.updateSettings({ timeout: 123 }) var p2 = group2.updateSettings({ timeout: 456 }) return Promise.all([p1, p2]) .then(function () { c.mustEqual(group1.timeout, 123) c.mustEqual(group2.timeout, 456) }) }) it('Should update its limiter options', function () { c = makeTest() var group = new Bottleneck.Group({ maxConcurrent: 1, minTime: 100 }) var limiter1 = group.key('AAA') c.mustEqual(limiter1._store.storeOptions.minTime, 100) group.updateSettings({ minTime: 200 }) c.mustEqual(limiter1._store.storeOptions.minTime, 100) var limiter2 = group.key('BBB') c.mustEqual(limiter2._store.storeOptions.minTime, 200) }) it('Should support keys(), limiters(), deleteKey()', function () { c = makeTest() var group1 = new Bottleneck.Group({ maxConcurrent: 1 }) var KEY_A = "AAA" var KEY_B = "BBB" return Promise.all([ c.pNoErrVal(group1.key(KEY_A).schedule(c.promise, null, 1), 1), c.pNoErrVal(group1.key(KEY_B).schedule(c.promise, null, 2), 2) ]) .then(function () { var keys = group1.keys() var limiters = group1.limiters() c.mustEqual(keys, [KEY_A, KEY_B]) c.mustEqual(limiters.length, 2) limiters.forEach(function (limiter, i) { c.mustEqual(limiter.key, keys[i]) assert(limiter.limiter instanceof Bottleneck) }) return group1.deleteKey(KEY_A) }) .then(function (deleted) { c.mustEqual(deleted, true) c.mustEqual(group1.keys().length, 1) return group1.deleteKey(KEY_A) }) .then(function (deleted) { c.mustEqual(deleted, false) c.mustEqual(group1.keys().length, 1) }) }) it('Should call autocleanup', function () { var KEY = 'test-key' var group = new Bottleneck.Group({ maxConcurrent: 1 }) group.updateSettings({ timeout: 50 }) c = makeTest({ id: 'something', timeout: group.timeout }) group.instances[KEY] = c.limiter return group.key(KEY).schedule(function () { return Promise.resolve() }) .then(function () { assert(group.instances[KEY] != null) return new Promise(function (resolve, reject) { setTimeout(resolve, 100) }) }) .then(function () { assert(group.instances[KEY] == null) }) }) })