from __future__ import annotations import asyncio import time from collections import deque class RateLimiter: def __init__(self, requests_per_second: float = 1.0) -> None: self._min_interval = 1.0 / requests_per_second self._timestamps: deque[float] = deque() self._lock = asyncio.Lock() async def acquire(self) -> None: async with self._lock: now = time.monotonic() while self._timestamps and self._timestamps[0] <= now - self._min_interval: self._timestamps.popleft() if self._timestamps: wait_time = self._timestamps[0] + self._min_interval - now if wait_time > 0: await asyncio.sleep(wait_time) self._timestamps.append(time.monotonic())