Real limiters don't throttle everyone together β they throttle each client, API key, or IP independently. Wrap any limiter strategy in a keyed limiter that lazily creates one limiter per key.
Implement KeyedRateLimiter:
__init__(factory) β factory is a zero-arg callable that returns a fresh limiter (e.g. lambda: TokenBucket(5, 1, clock))allow(key) β get or create the limiter for key, then delegate to its allow()Each key gets its own independent budget. FixedWindowLimiter is provided so your tests can build a factory.
import time
class FixedWindowLimiter:
def __init__(self, limit, window, clock=time.time):
self.limit = limit
self.window = window
self.clock = clock
self._window_index = None
self._count = 0
def allow(self):
index = int(self.clock() // self.window)
if index != self._window_index:
self._window_index = index
self._count = 0
if self._count < self.limit:
self._count += 1
return True
return False
class KeyedRateLimiter:
def __init__(self, factory):
self.factory = factory # zero-arg callable -> a new limiter
self._limiters = {}
def allow(self, key):
"""Get or create the limiter for the key, then delegate to its allow()."""
# TODO:
# if key not in self._limiters: self._limiters[key] = self.factory()
# return self._limiters[key].allow()
pass
The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.
Real limiters don't throttle everyone together β they throttle each client, API key, or IP independently. Wrap any limiter strategy in a keyed limiter that lazily creates one limiter per key.
Implement KeyedRateLimiter:
__init__(factory) β factory is a zero-arg callable that returns a fresh limiter (e.g. lambda: TokenBucket(5, 1, clock))allow(key) β get or create the limiter for key, then delegate to its allow()Each key gets its own independent budget. FixedWindowLimiter is provided so your tests can build a factory.
Press Run Tests or ββ© to check your solution.