All MicroEvals
Fai code review di questa implementazione cercando bug reali...
Create MicroEval
Header image for Fai code review di questa implementazione cercando bug reali...

Fai code review di questa implementazione cercando bug reali...

Prompt

Fai code review di questa implementazione cercando bug reali ed edge case, senza riscriverla se è corretta. import asyncio from typing import Callable, Awaitable, TypeVar, Tuple, Type, Optional T = TypeVar("T") async def retry_async( fn: Callable[[], Awaitable[T]], *, attempts: int = 3, base_delay: float = 0.1, retry_on: Tuple[Type[Exception], ...] = (Exception,), sleep: Callable[[float], Awaitable[object]] = asyncio.sleep, ) -> T: """Retry an async callable on selected exceptions with exponential back‑off. Args: fn: Async callable that takes no arguments. attempts: Maximum number of **total** attempts (including the first one). base_delay: Initial delay between retries (seconds). retry_on: Tuple of exception types that should be retried. sleep: Async function used to wait (default ``asyncio.sleep``); injected for easier testing. Returns: The result returned by ``fn``. Raises: ValueError: If ``attempts`` is less than 1. Exception: The last exception that failed after all attempts, provided it matches ``retry_on``. """ if attempts < 1: raise ValueError("attempts must be >= 1") last_exc: Optional[Exception] = None for attempt in range(1, attempts + 1): try: return await fn() except Exception as exc: # pragma: no‑cover – we want to be explicit if not isinstance(exc, retry_on): raise # non‑retryable → propagate immediately last_exc = exc # No sleep after the final attempt if attempt == attempts: break # exponential back‑off: base_delay * 2^(attempt‑1) delay = base_delay * (2 ** (attempt - 1)) await sleep(delay) # All attempts exhausted – re‑raise the last retryable exception raise last_exc