Run an async database operation with session retry.
(
session_maker: async_sessionmaker,
operation: Callable[[AsyncSession], Awaitable[Any]],
max_retry_times: int = 2,
max_retry_interval: float = 1.0,
)
| 19 | |
| 20 | |
| 21 | async def async_run_with_retry_session( |
| 22 | session_maker: async_sessionmaker, |
| 23 | operation: Callable[[AsyncSession], Awaitable[Any]], |
| 24 | max_retry_times: int = 2, |
| 25 | max_retry_interval: float = 1.0, |
| 26 | ) -> Any: |
| 27 | """Run an async database operation with session retry.""" |
| 28 | logger = get_logger(__name__) |
| 29 | max_retry_times = max(1, max_retry_times) |
| 30 | |
| 31 | for attempt in range(max_retry_times): |
| 32 | async with session_maker() as session: |
| 33 | try: |
| 34 | async with session.begin(): |
| 35 | result = await operation(session) |
| 36 | return result |
| 37 | except StopAsyncIteration: |
| 38 | raise |
| 39 | except Exception as exc: |
| 40 | logger.warning( |
| 41 | "Async attempt %s failed, retrying in %s seconds...", |
| 42 | attempt + 1, |
| 43 | max_retry_interval, |
| 44 | ) |
| 45 | logger.warning("trace = %s", traceback.format_exc()) |
| 46 | if attempt < max_retry_times - 1: |
| 47 | await asyncio.sleep(max_retry_interval) |
| 48 | continue |
| 49 | logger.error("Max retry attempts reached, raising exception.") |
| 50 | raise exc |
| 51 | |
| 52 | raise RuntimeError("async_run_with_retry_session exhausted without raising") |
no test coverage detected