import asyncio
import random
from typing import Awaitable, Callable, TypeVar
T = TypeVar("T")
async def aretry(
fn: Callable[[], Awaitable[T]],
attempts: int = 5,
base: float = 0.2,
should_retry: Callable[[BaseException], bool] = lambda _: True,
) -> T:
last: BaseException | None = None
for i in range(1, attempts + 1):
try:
return await fn()
except BaseException as e:
last = e
if i == attempts or not should_retry(e):
raise
delay = base * (2 ** (i - 1))
await asyncio.sleep(delay + random.random() * delay)
raise RuntimeError("unreachable") from last
async def flaky():
if random.random() < 0.8:
raise ConnectionError("oops")
return "ok"
print(asyncio.run(aretry(flaky, attempts=10)))
Create a free account and build your private vault. Share publicly whenever you want.