UNPKG

bucket-queue

Version:

A queue with leaky bucket logic made for promises

289 lines (227 loc) 7.77 kB
'use strict'; function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } var test = require('ava'); var defer = require('promise-defer'); var BucketQueue = require('./'); var makeCompareState = function makeCompareState(q, equal) { return function (want) { var message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'same state'; var got = q.getState(); var desired = Object.assign({}, got, want); equal(got, desired, message); }; }; test('should maintain proper state', function () { var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(t) { var q, compareState, d, value, p, result; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: q = BucketQueue({ calls: 1, perInterval: 150 }); compareState = makeCompareState(q, function (got, want, message) { t.deepEqual(got, want, message); }); compareState({ waiting: false, bucketCount: 0, queueCount: 0, concurrent: 0 }, 'initialized queue'); d = defer(); value = 'cat'; p = q.add(function () { return d.promise; }); compareState({ waiting: false, bucketCount: 0, queueCount: 1, concurrent: 0 }, 'added promise returning function to the queue'); // start q._tick(0); compareState({ waiting: true, bucketCount: 1, queueCount: 0, concurrent: 1 }, 'function popped off the queue and called'); d.resolve(value); _context.next = 12; return p; case 12: result = _context.sent; t.is(result, value, 'promise resolve value should be: ' + value); compareState({ waiting: true, bucketCount: 1, queueCount: 0, concurrent: 0 }, 'promise resolved'); q._tick(50); compareState({ waiting: true, bucketCount: 1, queueCount: 0, concurrent: 0 }, 'countdown is at 150ms'); q._tick(150); compareState({ waiting: false, bucketCount: 0, queueCount: 0, concurrent: 0 }, 'countdown is at 0ms and bucketCount is reset'); case 19: case 'end': return _context.stop(); } } }, _callee, undefined); })); return function (_x2) { return _ref.apply(this, arguments); }; }()); test('should throttle calls', function () { var _ref2 = _asyncToGenerator(regeneratorRuntime.mark(function _callee2(t) { var q, compareState, d1, d2, d3, p1, p2, p3, value1, result1, value2, result2, value3, result3; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: q = BucketQueue({ calls: 2, perInterval: 200 }); compareState = makeCompareState(q, function (got, want, message) { t.deepEqual(got, want, message); }); compareState({ waiting: false, bucketCount: 0, queueCount: 0, concurrent: 0 }, 'initialized queue'); d1 = defer(); d2 = defer(); d3 = defer(); p1 = q.add(function () { return d1.promise; }); p2 = q.add(function () { return d2.promise; }); p3 = q.add(function () { return d3.promise; }); compareState({ waiting: false, bucketCount: 0, queueCount: 3, concurrent: 0 }, 'added 3 promise returning fuctions to queue'); // start q._tick(0); compareState({ waiting: true, bucketCount: 2, queueCount: 1, concurrent: 2 }, 'max functions poped off the queue and called'); q._tick(50); compareState({ waiting: true, bucketCount: 2, queueCount: 1, concurrent: 2 }, 'countdown is at 150ms'); value1 = 'cat'; d1.resolve(value1); _context2.next = 18; return p1; case 18: result1 = _context2.sent; t.is(result1, value1, 'promise1 resolve value should be: ' + value1); compareState({ waiting: true, bucketCount: 2, queueCount: 1, concurrent: 1 }, 'promise 1 resolves'); q._tick(50); compareState({ waiting: true, bucketCount: 2, queueCount: 1, concurrent: 1 }, 'countdown is at 100ms'); value2 = 'mouse'; d2.resolve(value2); _context2.next = 27; return p2; case 27: result2 = _context2.sent; t.is(result2, value2, 'promise2 resolve value should be: ' + value2); compareState({ waiting: true, bucketCount: 2, queueCount: 1, concurrent: 0 }, 'promise 2 resolves'); q._tick(50); compareState({ waiting: true, bucketCount: 2, queueCount: 1, concurrent: 0 }, 'countdown is at 50ms'); q._tick(50); compareState({ waiting: false, bucketCount: 1, queueCount: 0, concurrent: 1 }, 'countdown finished and function3 popped off the queue and called'); value3 = 'cheese'; d3.resolve(value3); _context2.next = 38; return p3; case 38: result3 = _context2.sent; t.is(result3, value3, 'promise3 resolve value should be: ' + value3); compareState({ waiting: false, bucketCount: 1, queueCount: 0, concurrent: 0 }, 'promise 3 resolves'); q._tick(50); compareState({ waiting: false, bucketCount: 1, queueCount: 0, concurrent: 0 }, 'countdown is at 150ms'); q._tick(150); compareState({ waiting: false, bucketCount: 0, queueCount: 0, concurrent: 0 }, 'countdown is at 0ms and bucketCount is reset'); case 45: case 'end': return _context2.stop(); } } }, _callee2, undefined); })); return function (_x3) { return _ref2.apply(this, arguments); }; }());