Spaces:
Running
Running
File size: 2,476 Bytes
30c32c8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
const Timer = require('../util/timer');
class RateLimiter {
/**
* A utility for limiting the rate of repetitive send operations, such as
* bluetooth messages being sent to hardware devices. It uses the token bucket
* strategy: a counter accumulates tokens at a steady rate, and each send costs
* a token. If no tokens remain, it's not okay to send.
* @param {number} maxRate the maximum number of sends allowed per second
* @constructor
*/
constructor (maxRate) {
/**
* The maximum number of tokens.
* @type {number}
*/
this._maxTokens = maxRate;
/**
* The interval in milliseconds for refilling one token. It is calculated
* so that the tokens will be filled to maximum in one second.
* @type {number}
*/
this._refillInterval = 1000 / maxRate;
/**
* The current number of tokens in the bucket.
* @type {number}
*/
this._count = this._maxTokens;
this._timer = new Timer();
this._timer.start();
/**
* The last time in milliseconds when the token count was updated.
* @type {number}
*/
this._lastUpdateTime = this._timer.timeElapsed();
}
/**
* Check if it is okay to send a message, by updating the token count,
* taking a token and then checking if we are still under the rate limit.
* @return {boolean} true if we are under the rate limit
*/
okayToSend () {
// Calculate the number of tokens to refill the bucket with, based on the
// amount of time since the last refill.
const now = this._timer.timeElapsed();
const timeSinceRefill = now - this._lastUpdateTime;
const refillCount = Math.floor(timeSinceRefill / this._refillInterval);
// If we're adding at least one token, reset _lastUpdateTime to now.
// Otherwise, don't reset it so that we can continue measuring time until
// the next refill.
if (refillCount > 0) {
this._lastUpdateTime = now;
}
// Refill the tokens up to the maximum
this._count = Math.min(this._maxTokens, this._count + refillCount);
// If we have at least one token, use one, and it's okay to send.
if (this._count > 0) {
this._count--;
return true;
}
return false;
}
}
module.exports = RateLimiter;
|