Event Rate Limiting (Rolling Window)
Per-type queue + sliding window
TimeO(n)SpaceO(k · L), k = types, L = max events per type in windowGood solution
One pass over events. Each timestamp is added once and removed at most once from its queue. Optimal for this problem.
Code
1type RateLimitEvent = { type: string; timestamp: number };
2
3function rateLimit(events: RateLimitEvent[], limit: number, windowMs: number): RateLimitEvent[] {
4 const queues = new Map<string, number[]>(); // type -> timestamps kept in window
5 const result: RateLimitEvent[] = [];
6
7 for (const e of events) {
8 const q = queues.get(e.type) ?? [];
9 queues.set(e.type, q);
10
11 const threshold = e.timestamp - windowMs;
12
13 // Remove expired timestamps from the front
14 while (q.length > 0 && q[0] < threshold) {
15 q.shift();
16 }
17
18 if (q.length < limit) {
19 q.push(e.timestamp);
20 result.push(e);
21 }
22 // else: drop it
23 }
24
25 return result;
26}
27
28const events: RateLimitEvent[] = [
29 { type: 'click', timestamp: 1000 },
30 { type: 'click', timestamp: 1001 },
31 { type: 'click', timestamp: 1002 },
32 { type: 'click', timestamp: 1003 },
33 { type: 'click', timestamp: 1004 },
34 { type: 'click', timestamp: 1005 },
35 { type: 'click', timestamp: 1006 },
36 { type: 'click', timestamp: 1007 },
37];
38
39const limitedEvents = rateLimit(events, 3, 5);
40console.log(limitedEvents);
41
42Animation
Limit: 3 per type in window 5ms
Input
clickt=1000
clickt=1001
clickt=1002
clickt=1003
clickt=1004
clickt=1005
clickt=1006
clickt=1007
Output
(accepted events)
Speed: