Loading files
// In-memory sliding-window rate limiter. This app runs as a single long-lived
// process (the Pi), so process memory is a perfectly good store — no Redis.
const buckets = new Map<string, number[]>();
/** Returns true when the call is allowed, false when over the limit. */
export function rateLimit(key: string, limit: number, windowMs: number): boolean {
const now = Date.now();
const cutoff = now - windowMs;
const hits = (buckets.get(key) ?? []).filter((t) => t > cutoff);
if (hits.length >= limit) {
buckets.set(key, hits);
return false;
}
hits.push(now);
buckets.set(key, hits);
// Opportunistic cleanup so long-idle keys don't accumulate forever.
if (buckets.size > 10_000) {
for (const [k, v] of buckets) {
if (v.every((t) => t <= cutoff)) buckets.delete(k);
}
}
return true;
}
07e931b46This file is pinned to the selected release. Download the original to open it in your design tool.