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(); });