"""Rate limiting for TfL API requests.""" import asyncio import warnings from .config import REQUESTS_PER_MIN class RateLimiter: """Rate limiter enforcing max requests per minute.""" def __init__(self): self.request_times: list[float] = [] self._lock = asyncio.Lock() async def acquire(self): """Wait until we can make a request within rate limits.""" async with self._lock: now = asyncio.get_event_loop().time() cutoff = now - 10.0 # 10 seconds self.request_times = [t for t in self.request_times if t > cutoff] if ( len(self.request_times) >= REQUESTS_PER_MIN // 6 ): # we look at it every 10 seconds instead of minutes wait_time = self.request_times[0] - cutoff if wait_time > 0: warnings.warn( f"Rate limit reached ({REQUESTS_PER_MIN}/min), " f"waiting {wait_time:.1f}s", stacklevel=1, ) await asyncio.sleep(wait_time) self.request_times.append(asyncio.get_event_loop().time())