cvsa/test/mq/rateLimiter.test.ts

92 lines
2.8 KiB
TypeScript

import { assertEquals } from "jsr:@std/assert";
import { SlidingWindow } from "lib/mq/slidingWindow.ts";
import { RateLimiter, RateLimiterConfig } from "lib/mq/rateLimiter.ts";
import { Redis } from "npm:ioredis@5.5.0";
Deno.test("RateLimiter works correctly", async () => {
const redis = new Redis({ maxRetriesPerRequest: null });
const windowSize = 5;
const maxRequests = 10;
const slidingWindow = new SlidingWindow(redis, windowSize);
const config: RateLimiterConfig = {
window: slidingWindow,
max: maxRequests,
};
const rateLimiter = new RateLimiter("test_event", [config]);
await rateLimiter.clear();
// Initial availability should be true
assertEquals(await rateLimiter.getAvailability(), true);
// Trigger events up to the limit
for (let i = 0; i < maxRequests; i++) {
await rateLimiter.trigger();
}
// Availability should now be false
assertEquals(await rateLimiter.getAvailability(), false);
// Wait for the window to slide
await new Promise((resolve) => setTimeout(resolve, windowSize * 1000 + 500));
// Availability should be true again
assertEquals(await rateLimiter.getAvailability(), true);
redis.quit();
});
Deno.test("Multiple configs work correctly", async () => {
const redis = new Redis({ maxRetriesPerRequest: null });
const windowSize1 = 1;
const maxRequests1 = 2;
const windowSize2 = 5;
const maxRequests2 = 6;
const slidingWindow1 = new SlidingWindow(redis, windowSize1);
const config1: RateLimiterConfig = {
window: slidingWindow1,
max: maxRequests1,
};
const slidingWindow2 = new SlidingWindow(redis, windowSize2);
const config2: RateLimiterConfig = {
window: slidingWindow2,
max: maxRequests2,
};
const rateLimiter = new RateLimiter("test_event_multi", [config1, config2]);
await rateLimiter.clear();
// Initial availability should be true
assertEquals(await rateLimiter.getAvailability(), true);
// Trigger events up to the limit of the first config
for (let i = 0; i < maxRequests1; i++) {
await rateLimiter.trigger();
}
// Availability should now be false (due to config1)
assertEquals(await rateLimiter.getAvailability(), false);
// Wait for the first window to slide
await new Promise((resolve) => setTimeout(resolve, windowSize1 * 1000 + 500));
// Availability should now be true (due to config1)
assertEquals(await rateLimiter.getAvailability(), true);
// Trigger events up to the limit of the second config
for (let i = maxRequests1; i < maxRequests2; i++) {
await rateLimiter.trigger();
}
// Availability should still be false (due to config2)
assertEquals(await rateLimiter.getAvailability(), false);
// Wait for the second window to slide
await new Promise((resolve) => setTimeout(resolve, windowSize2 * 1000 + 500));
// Availability should be true again
assertEquals(await rateLimiter.getAvailability(), true);
redis.quit();
});