41 lines
1.5 KiB
TypeScript
41 lines
1.5 KiB
TypeScript
import { logger } from "@pkg/logger";
|
|
|
|
export class RateLimiter {
|
|
private requestTimestamps: number[] = [];
|
|
private readonly callsPerMinute: number;
|
|
|
|
constructor(callsPerMinute: number = 60) {
|
|
this.callsPerMinute = Math.min(callsPerMinute, 60);
|
|
}
|
|
|
|
async checkRateLimit(): Promise<void> {
|
|
const currentTime = Date.now();
|
|
const oneMinuteAgo = currentTime - 60000; // 60 seconds in milliseconds
|
|
|
|
// Remove timestamps older than 1 minute
|
|
this.requestTimestamps = this.requestTimestamps.filter(
|
|
(timestamp) => timestamp > oneMinuteAgo,
|
|
);
|
|
|
|
// If we're approaching the limit, wait until we have capacity
|
|
if (this.requestTimestamps.length >= this.callsPerMinute) {
|
|
const oldestRequest = this.requestTimestamps[0];
|
|
const waitTime = oldestRequest + 60000 - currentTime;
|
|
|
|
if (waitTime > 0) {
|
|
logger.warn(
|
|
`Rate limit approaching (${this.requestTimestamps.length} requests in last minute). Sleeping for ${waitTime}ms`,
|
|
);
|
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
// After waiting, some timestamps may have expired
|
|
this.requestTimestamps = this.requestTimestamps.filter(
|
|
(timestamp) => timestamp > Date.now() - 60000,
|
|
);
|
|
}
|
|
}
|
|
|
|
// Add current request to timestamps
|
|
this.requestTimestamps.push(Date.now());
|
|
}
|
|
}
|