Files
2026-07-14 08:59:05 +05:00

29 lines
1.2 KiB
Python

import asyncio
import random
class RateLimiter:
"""Гарантирует минимальный интервал между вызовами wait(), плюс джиттер.
Semaphore ограничивает только количество одновременных запросов - можно
держать его хоть в 1, но всё равно долбить сайт пачками сразу как
освобождается слот. Этот класс решает именно это: не чаще чем раз
в min_interval секунд, сколько бы корутин ни стояло в очереди.
"""
def __init__(self, min_interval: float, jitter: float = 0.0):
self.min_interval = min_interval
self.jitter = jitter
self._lock = asyncio.Lock()
self._last_call = 0.0
async def wait(self):
async with self._lock:
loop = asyncio.get_event_loop()
now = loop.time()
delay = self.min_interval + random.uniform(0, self.jitter)
sleep_for = delay - (now - self._last_call)
if sleep_for > 0:
await asyncio.sleep(sleep_for)
self._last_call = loop.time()