fix: bound rate limiter maps to prevent memory growth

Add MAX_MAP_SIZE (10,000) cap to botHitCounts Map. During the 5-minute
cleanup interval, evict oldest entries when the map exceeds the limit.
Export cleanupInterval handle for graceful shutdown.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-08 20:41:57 +00:00
co-authored by Claude Opus 4.6
parent f62323c59f
commit d98b264935
+9 -1
View File
@@ -2,14 +2,22 @@ import type { Context, Next } from 'hono'
const isDev = process.env.NODE_ENV !== 'production' const isDev = process.env.NODE_ENV !== 'production'
const MAX_MAP_SIZE = 10_000
const hitCounts = new Map<string, { count: number; resetAt: number }>() const hitCounts = new Map<string, { count: number; resetAt: number }>()
// Cleanup stale entries every 5 minutes // Cleanup stale entries every 5 minutes + evict oldest if over MAX_MAP_SIZE
export const cleanupInterval = setInterval(() => { export const cleanupInterval = setInterval(() => {
const now = Date.now() const now = Date.now()
for (const [key, entry] of hitCounts) { for (const [key, entry] of hitCounts) {
if (now > entry.resetAt) hitCounts.delete(key) if (now > entry.resetAt) hitCounts.delete(key)
} }
// Evict oldest entries from botHitCounts if over limit
if (botHitCounts.size > MAX_MAP_SIZE) {
const sorted = [...botHitCounts.entries()].sort((a, b) => a[1] - b[1])
const toRemove = sorted.slice(0, botHitCounts.size - MAX_MAP_SIZE)
for (const [key] of toRemove) botHitCounts.delete(key)
}
}, 5 * 60 * 1000) }, 5 * 60 * 1000)
export function rateLimit(windowMs: number, maxHits: number) { export function rateLimit(windowMs: number, maxHits: number) {