from __future__ import annotations import asyncio import time class MatrixRateLimiter: def __init__(self, max_requests: int = 30, per_seconds: float = 1.0): self._tokens = float(max_requests) self._max = max_requests self._rate = per_seconds self._last_refill = time.monotonic() self._lock = asyncio.Lock() async def acquire(self) -> None: async with self._lock: now = time.monotonic() elapsed = now - self._last_refill refill = elapsed / self._rate * self._max self._tokens = min(self._max, self._tokens + refill) self._last_refill = now if self._tokens < 1: wait = self._rate / self._max await asyncio.sleep(wait) self._tokens = 1 self._tokens -= 1