import asyncio from typing import Awaitable, Callable, TypeVar from app.core.constants import MAX_RETRIES T = TypeVar("T") class RetryExecutor: async def run(self, operation: Callable[[], Awaitable[T]]) -> T: last_error: Exception | None = None for attempt in range(1, MAX_RETRIES + 1): try: return await operation() except (TimeoutError, ConnectionError, OSError) as exc: last_error = exc if attempt == MAX_RETRIES: break await asyncio.sleep(0.1 * attempt) assert last_error is not None raise last_error