UNPKG

rate-keeper

Version:

A lightweight utility for easily adding rate limiting to functions, ideal for preventing API rate limit violations.

82 lines 3.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DropPolicy = void 0; exports.default = RateKeeper; const globalRateData = new Map(); /** * @enum {DropPolicy} Defines the behavior of the queue when the maximum size has been reached. */ var DropPolicy; (function (DropPolicy) { DropPolicy[DropPolicy["Reject"] = 0] = "Reject"; DropPolicy[DropPolicy["DropOldest"] = 1] = "DropOldest"; })(DropPolicy || (exports.DropPolicy = DropPolicy = {})); class LimitData { constructor(settings) { this.queue = []; this.timer = null; this.settings = settings; } } function getRateData(settings) { const { id } = settings; if (globalRateData.has(id)) { return globalRateData.get(id); } else { const newLimitData = new LimitData(settings); globalRateData.set(id, newLimitData); return newLimitData; } } /** * @param {(...args: Args) => Result} action The action to be rate-limited. * @param {number} rateLimit The minimum interval in milliseconds between each execution. * @param {QueueSettings} settings Optional. Queue settings for rate limiting and execution. * @returns {(...args: Args) => Promise<Result>} An asynchronous function that executes the action and returns a promise with the result. */ function RateKeeper(action, rateLimit, settings = { id: 0 }) { const limitData = settings.id === 0 ? new LimitData(settings) : getRateData(settings); function processQueue() { var _a, _b; (_b = (_a = limitData.queue.shift()) === null || _a === void 0 ? void 0 : _a.action) === null || _b === void 0 ? void 0 : _b.call(_a); if (limitData.queue.length === 0 && limitData.timer !== null) { clearInterval(limitData.timer); limitData.timer = null; } } function publicFunc(...args) { var _a; const { maxQueueSize, dropPolicy } = limitData.settings; let resolve; let reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); // Handle queue size limit if (maxQueueSize !== undefined && limitData.queue.length >= maxQueueSize) { if (dropPolicy === DropPolicy.Reject) { // Reject new task by immediately resolving with a rejection return Promise.reject(new Error("Queue is at max capacity.")); } else if (dropPolicy === DropPolicy.DropOldest) { // Drop the oldest task in the queue (_a = limitData.queue.shift()) === null || _a === void 0 ? void 0 : _a.reject(new Error("Queue is at max capacity.")); } } // Add the new task to the queue limitData.queue.push({ action: () => resolve(action(...args)), reject: (reason) => { reject(reason); } }); // Start the timer if it isn’t already running if (limitData.timer === null) { processQueue(); limitData.timer = setInterval(processQueue, rateLimit); } return promise; } return publicFunc; } //# sourceMappingURL=index.js.map