From 247b892d7ba82318d8749c166395cbd2e3a4c56b Mon Sep 17 00:00:00 2001 From: megawac Date: Tue, 8 Nov 2016 23:13:33 -0500 Subject: [PATCH] Initial token bucket implementation (#1314) --- lib/internal/TokenBucket.js | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 lib/internal/TokenBucket.js diff --git a/lib/internal/TokenBucket.js b/lib/internal/TokenBucket.js new file mode 100644 index 000000000..993036301 --- /dev/null +++ b/lib/internal/TokenBucket.js @@ -0,0 +1,39 @@ +import DLL from './DoublyLinkedList'; + +/** + * An internal implementation of [Token Bucket](https://en.wikipedia.org/wiki/Token_bucket) + * for rate-limiting/traffic shaping. + * + * @param {Number} bucketSize - the maximum number of items (inclusive) which can be queued in + * a interval of time. + * @param {Number} interval - the period in miliseconds to stop tracking a sent item + */ +export function TokenBucket(bucketSize, interval) { + this.bucketSize = bucketSize; + this.interval = interval; + this.queue = new DLL(); + this.queued = 0; // Number of items sent + size of queue +} + +/** + * Enqueue an operation to be executed + */ +TokenBucket.prototype.enqueue = function(operation) { + this.queued++; + if (this.queued <= this.bucketSize) { + operation(); + } else { + this.queue.push(operation); + } + + // after interval, decrement the queued count and call a queued operation (if bucket is full) + setTimeout(onIntervalComplete, this.interval, this); +} + +function onIntervalComplete(bucket) { + bucket.queued--; + if (bucket.queue.length > 0) { + // call first queued operation + (bucket.queue.shift())(); + } +}