Spaces:
Paused
Paused
| import asyncio | |
| from typing import TypeVar, Callable, Awaitable, Optional | |
| T = TypeVar("T") | |
| async def retry( | |
| fn: Callable[[], Awaitable[T]], | |
| max_attempts: int = 3, | |
| delay_seconds: int = 1, | |
| ) -> T: | |
| """ | |
| Retry an async function with exponential backoff. | |
| Args: | |
| fn: The async function to retry | |
| max_attempts: Maximum number of attempts | |
| delay_seconds: Delay between attempts in seconds | |
| Returns: | |
| The result of the function call | |
| Raises: | |
| The last exception if all attempts fail | |
| Example: | |
| ```python | |
| async def fetch_data(): | |
| # Some operation that might fail | |
| return await api_call() | |
| try: | |
| result = await retry(fetch_data, max_attempts=3, delay_seconds=2) | |
| print(f"Success: {result}") | |
| except Exception as e: | |
| print(f"Failed after all retries: {e}") | |
| ``` | |
| """ | |
| if max_attempts <= 0: | |
| raise ValueError("max_attempts must be greater than zero") | |
| last_error: Optional[Exception] = None | |
| for attempt in range(1, max_attempts + 1): | |
| try: | |
| return await fn() | |
| except Exception as error: | |
| last_error = error | |
| if attempt == max_attempts: | |
| break | |
| await asyncio.sleep(delay_seconds) | |
| if last_error: | |
| raise last_error | |
| raise RuntimeError("Unexpected: last_error is None") | |