p-ratelimit
Version:
Promise-based utility to make sure you don’t call rate-limited APIs too quickly.
64 lines • 2.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.QuotaManager = void 0;
const dequeue_1 = require("../dequeue");
/** keep track of API invocations, allowing or disallowing them based on our quota */
class QuotaManager {
constructor(_quota) {
this._quota = _quota;
this._activeCount = 0;
this.history = new dequeue_1.Dequeue();
if (typeof _quota !== 'object') {
console.warn('[p-ratelimit QuotaManager] A QuotaManager was created with no quota.');
this._quota = {};
}
if (('interval' in this._quota && !('rate' in this._quota)) ||
('rate' in this._quota && !('interval' in this._quota))) {
const msg = `[p-ratelimit QuotaManager] Invalid Quota: for a rate-limit quota, both ` +
`interval and rate must be specified.`;
throw new Error(msg);
}
}
/** The current quota */
get quota() {
return Object.assign({}, this._quota);
}
/** The number of currently-active invocations */
get activeCount() {
return this._activeCount;
}
/** Max amount of time a queued request can wait before throwing a timeout error */
get maxDelay() {
return this._quota.maxDelay || 0;
}
/**
* Log that an invocation started.
* @returns true if the invocation was allowed, false if not (you can try again later)
*/
start() {
if (this._activeCount >= this._quota.concurrency) {
return false;
}
if (this._quota.interval !== undefined && this._quota.rate !== undefined) {
this.removeExpiredHistory();
if (this.history.length >= this._quota.rate) {
return false;
}
this.history.push(Date.now());
}
this._activeCount++;
return true;
}
/** Log that an invocation ended */
end() {
this._activeCount--;
}
removeExpiredHistory() {
const expired = Date.now() - this._quota.interval;
while (this.history.length && this.history.peekFront() < expired) {
this.history.shift();
}
}
}
exports.QuotaManager = QuotaManager;
//# sourceMappingURL=quotaManager.js.map