UNPKG

leaky-bucket-queue

Version:

An implementation of burstable throtling algorithm on top of rxjs

97 lines 3.55 kB
import { timer, Subject, } from 'rxjs'; import { ArgumentError } from './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 Subject(); this.queue = []; this.timerStarted = false; this.assertOption(option); this.bucket = option.burstSize; } LeakyBucketQueue.prototype.assertOption = function (option) { if (!option) { throw 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.createFromArgumentName(name, 'exist and be a number'); } if (value < 0) { throw 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 = 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; }()); export { LeakyBucketQueue }; //# sourceMappingURL=LeakyBucketQueue.js.map