UNPKG

congress-dot-gov

Version:
66 lines (63 loc) 2.27 kB
'use strict'; class AdaptiveRateLimiter { config; lastRequestTime = 0; currentDelay = 0; hourStartTime = Date.now(); constructor(config = {}) { this.config = { safetyMargin: config.safetyMargin ?? 0.1, // 10% safety margin minDelay: config.minDelay ?? 50, // 50ms minimum maxDelay: config.maxDelay ?? 3e4 // 30 seconds maximum }; this.currentDelay = this.config.minDelay; } /** * Call this before making an API request. It will wait the appropriate * amount of time based on current rate limit status. * @returns A promise that resolves when the next request can be made */ async waitForNextRequest() { const now = Date.now(); if (now - this.hourStartTime >= 36e5) { this.hourStartTime = now; this.currentDelay = this.config.minDelay; } const timeSinceLastRequest = now - this.lastRequestTime; const delayNeeded = this.currentDelay - timeSinceLastRequest; if (delayNeeded > 0) { await this.sleep(delayNeeded); } this.lastRequestTime = Date.now(); } /** * Calculate delay based on amount of time remaining in the hour and number of requests remaining * @param rateLimitInfo - The current rate limit info * @param currentTime - The current time * @returns The delay in milliseconds */ calculateDelay(rateLimitInfo, currentTime) { const { limit, remaining } = rateLimitInfo; const timeElapsedThisHour = currentTime - this.hourStartTime; const timeRemainingInHour = Math.max(100, 36e5 - timeElapsedThisHour); const safeRemaining = Math.floor(limit * this.config.safetyMargin); if (remaining <= safeRemaining) { return this.config.maxDelay; } const optimalDelay = timeRemainingInHour / remaining; const utilizationRatio = 1 - remaining / limit; const adaptiveDelay = optimalDelay * utilizationRatio; return Math.max(this.config.minDelay, Math.min(this.config.maxDelay, adaptiveDelay)); } sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } updateRateLimitInfo(rateLimitInfo) { this.currentDelay = this.calculateDelay(rateLimitInfo, Date.now()); this.lastRequestTime = Date.now(); } } exports.AdaptiveRateLimiter = AdaptiveRateLimiter;