UNPKG

leaky-bucket-queue

Version:

An implementation of burstable throtling algorithm on top of rxjs

99 lines 3.69 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var rxjs_1 = require("rxjs"); var ArgumentError_1 = require("./ArgumentError"); /** * This queue is a simple implementation of leaky bucket algorithm, in terms of number of emitted * object. The burst object will by default emitted synchronously. * @public */ var LeakyBucketQueue = /** @class */ (function () { function LeakyBucketQueue(option) { this.option = option; this.bucket = 3; this.subject = new rxjs_1.Subject(); this.queue = []; this.timerStarted = false; this.assertOption(option); this.bucket = option.burstSize; } LeakyBucketQueue.prototype.assertOption = function (option) { if (!option) { throw ArgumentError_1.ArgumentError.createFromArgumentName('option', 'not be null or undefined'); } this.assertValue('burstSize', option.burstSize); this.assertValue('period', option.period); }; LeakyBucketQueue.prototype.assertValue = function (name, value) { if (typeof value !== 'number') { throw ArgumentError_1.ArgumentError.createFromArgumentName(name, 'exist and be a number'); } if (value < 0) { throw ArgumentError_1.ArgumentError.createFromArgumentName(name, 'be larger than 0'); } }; LeakyBucketQueue.prototype.consume = function () { return this.subject.asObservable(); }; /** * Queues data for emit at scheduled time. By default burst will be emitted synchronously. If * consistency is desired (emit item like the delayed item, asynchronously), then a scheduler * could be used to override this behaviour. * @param data - data to be queued */ LeakyBucketQueue.prototype.enqueue = function (data) { var _this = this; this.queue.push(data); var _loop_1 = function () { this_1.bucket--; var data_1 = this_1.queue.shift(); if (this_1.option.scheduler) { this_1.option.scheduler.schedule(function () { return _this.subject.next(data_1); }); } else { this_1.subject.next(data_1); } }; var this_1 = this; while (this.bucket > 0 && this.queue[0]) { _loop_1(); } this.startTimer(); }; /** @internal */ LeakyBucketQueue.prototype.startTimer = function () { var _this = this; if (this.timerStarted) { return; } this.timer = rxjs_1.timer(this.option.period, this.option.period).subscribe({ next: function () { var data = _this.queue.shift(); if (data) { _this.subject.next(data); } else { _this.bucket++; } if (_this.bucket === _this.option.burstSize && _this.timer) { _this.timer.unsubscribe(); _this.timer = undefined; _this.timerStarted = false; } }, }); this.timerStarted = true; }; /** * Stops the leaky bucket timer and return remaining item on queue for persistence or clean up. */ LeakyBucketQueue.prototype.stop = function () { if (this.timer) { this.timer.unsubscribe(); } return this.queue; }; return LeakyBucketQueue; }()); exports.LeakyBucketQueue = LeakyBucketQueue; //# sourceMappingURL=LeakyBucketQueue.js.map