57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import { SlidingWindow } from "lib/mq/slidingWindow.ts";
|
|
|
|
export interface RateLimiterConfig {
|
|
window: SlidingWindow;
|
|
max: number;
|
|
}
|
|
|
|
export class RateLimiter {
|
|
private readonly configs: RateLimiterConfig[];
|
|
private readonly configEventNames: string[];
|
|
|
|
/*
|
|
* @param name The name of the rate limiter
|
|
* @param configs The configuration of the rate limiter, containing:
|
|
* - window: The sliding window to use
|
|
* - max: The maximum number of events allowed in the window
|
|
*/
|
|
constructor(name: string, configs: RateLimiterConfig[]) {
|
|
this.configs = configs;
|
|
this.configEventNames = configs.map((_, index) => `${name}_config_${index}`);
|
|
}
|
|
|
|
/*
|
|
* Check if the event has reached the rate limit
|
|
*/
|
|
async getAvailability(): Promise<boolean> {
|
|
for (let i = 0; i < this.configs.length; i++) {
|
|
const config = this.configs[i];
|
|
const eventName = this.configEventNames[i];
|
|
const count = await config.window.count(eventName);
|
|
if (count >= config.max) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Trigger an event in the rate limiter
|
|
*/
|
|
async trigger(): Promise<void> {
|
|
for (let i = 0; i < this.configs.length; i++) {
|
|
const config = this.configs[i];
|
|
const eventName = this.configEventNames[i];
|
|
await config.window.event(eventName);
|
|
}
|
|
}
|
|
|
|
async clear(): Promise<void> {
|
|
for (let i = 0; i < this.configs.length; i++) {
|
|
const config = this.configs[i];
|
|
const eventName = this.configEventNames[i];
|
|
await config.window.clear(eventName);
|
|
}
|
|
}
|
|
}
|