- Background task that refreshes stats every 3600 seconds (1 hour)
- Caches last posted stats for automatic reposting
- Graceful handling of refresh failures with error logging
- Optional feature that can be disabled with
auto_refresh=False
- Automatic detection of 429 status codes
- Header parsing for
Retry-Afterand rate limit info - Detailed logging of rate limit warnings and errors
- Exponential backoff retry strategy (1s, 2s, 4s delays)
- Real-time tracking of remaining requests
- Reset timestamp monitoring from API headers
- Warning system when < 10 requests remaining
- Public methods to check rate limit status
- Automatic retry on 429 errors with
@retry_with_backoff - Configurable max retries (default: 3) and base delay (default: 1.0s)
- Applied to critical methods:
post_bot_stats,post_shard_stats - Intelligent handling that doesn't retry non-rate-limit errors
# New initialization with rate limit tracking
def __init__(self, bot_token: str, bot_id: str, auto_refresh: bool = True):
# ... existing code ...
self._rate_limit_remaining: int = 100
self._rate_limit_reset: float = 0
# Enhanced session management
async def start_session(self):
# ... HTTP client setup ...
# Start hourly refresh task
if self.auto_refresh and self._refresh_task is None:
self._refresh_task = asyncio.create_task(self._hourly_refresh_loop())
# New hourly refresh loop
async def _hourly_refresh_loop(self):
while True:
await asyncio.sleep(3600) # 1 hour
if self._last_stats:
await self.post_bot_stats(**self._last_stats)
# Enhanced request method with 429 handling
async def _make_request(self, method: str, endpoint: str, data: Optional[Dict[str, Any]] = None):
# ... rate limit header parsing ...
if response.status_code == 429:
retry_after = response.headers.get("Retry-After", "60")
error_msg = f"Rate limited (429). Retry after {retry_after} seconds"
raise InfinityAPIError(error_msg, 429)
# Decorated methods with retry logic
@retry_with_backoff(max_retries=3, base_delay=1.0)
async def post_bot_stats(self, ...):
# ... stats caching for auto-refresh ...
self._last_stats = {...}
self._last_refresh = time.time()
# New monitoring methods
def get_rate_limit_info(self) -> Dict[str, Any]:
return {
"remaining": self._rate_limit_remaining,
"reset_timestamp": self._rate_limit_reset,
"reset_in_seconds": max(0, self._rate_limit_reset - time.time())
}
def get_auto_refresh_info(self) -> Dict[str, Any]:
return {
"enabled": self.auto_refresh,
"last_refresh": self._last_refresh,
"next_refresh": next_refresh,
"seconds_until_next": max(0, next_refresh - time.time()),
"has_stats_cached": self._last_stats is not None
}def retry_with_backoff(max_retries: int = 3, base_delay: float = 1.0):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
for attempt in range(max_retries):
try:
return await func(*args, **kwargs)
except InfinityAPIError as e:
if e.status_code == 429 and attempt < max_retries - 1:
delay = base_delay * (2 ** attempt)
print(f"⏳ Rate limited. Retrying in {delay:.1f}s...")
await asyncio.sleep(delay)
continue
raise
return wrapper
return decoratorasync with InfinityClient("token", "bot_id", auto_refresh=True) as client:
# Post stats - will be auto-refreshed every hour
await client.post_bot_stats(server_count=150, user_count=5000)
# Check refresh status
info = client.get_auto_refresh_info()
print(f"Next refresh in: {info['seconds_until_next']} seconds")# Before making requests
rate_info = client.get_rate_limit_info()
if rate_info['remaining'] < 5:
print("⚠️ Low on API requests!")
# After requests - automatically updated
rate_info = client.get_rate_limit_info()
print(f"Remaining: {rate_info['remaining']}")- Hands-off operation: Stats refresh automatically without user intervention
- Robust error handling: 429 errors don't break the bot, they're handled gracefully
- Better API citizenship: Respects rate limits and prevents excessive requests
- Visibility: Users can monitor their API usage in real-time
- Reliability: Exponential backoff ensures eventual success even under load
src/pyfinity/client.py- Core rate limiting and refresh logicREADME.md- Documentation of new featurestest_rate_limits.py- Test script for new functionality
Your Pyfinity implementation now includes enterprise-grade rate limiting and automatic refresh capabilities that will keep your bot's statistics current while respecting API limits and handling errors gracefully!