AI Researcher and Video Studio implementation complete
This commit is contained in:
57
backend/services/research/trends/rate_limiter.py
Normal file
57
backend/services/research/trends/rate_limiter.py
Normal file
@@ -0,0 +1,57 @@
|
||||
"""
|
||||
Rate Limiter for Google Trends API
|
||||
|
||||
Ensures we don't exceed Google Trends rate limits (1 request per second).
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from time import time
|
||||
from collections import deque
|
||||
from loguru import logger
|
||||
|
||||
|
||||
class RateLimiter:
|
||||
"""
|
||||
Simple rate limiter for Google Trends API.
|
||||
|
||||
Limits requests to max_calls per period (in seconds).
|
||||
"""
|
||||
|
||||
def __init__(self, max_calls: int = 1, period: float = 1.0):
|
||||
"""
|
||||
Initialize rate limiter.
|
||||
|
||||
Args:
|
||||
max_calls: Maximum number of calls allowed
|
||||
period: Time period in seconds
|
||||
"""
|
||||
self.max_calls = max_calls
|
||||
self.period = period
|
||||
self.calls = deque()
|
||||
self._lock = asyncio.Lock()
|
||||
|
||||
async def acquire(self):
|
||||
"""
|
||||
Acquire permission to make a request.
|
||||
|
||||
Will wait if rate limit would be exceeded.
|
||||
"""
|
||||
async with self._lock:
|
||||
now = time()
|
||||
|
||||
# Remove old calls outside the period
|
||||
while self.calls and self.calls[0] < now - self.period:
|
||||
self.calls.popleft()
|
||||
|
||||
# If at limit, wait until oldest call expires
|
||||
if len(self.calls) >= self.max_calls:
|
||||
sleep_time = self.period - (now - self.calls[0])
|
||||
if sleep_time > 0:
|
||||
logger.debug(f"Rate limit reached, waiting {sleep_time:.2f}s")
|
||||
await asyncio.sleep(sleep_time)
|
||||
# Recursively try again after waiting
|
||||
return await self.acquire()
|
||||
|
||||
# Record this call
|
||||
self.calls.append(time())
|
||||
logger.debug(f"Rate limit check passed, {len(self.calls)}/{self.max_calls} calls in period")
|
||||
Reference in New Issue
Block a user