mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-28 09:32:20 +00:00
feat(automation): add retry policy helper
This commit is contained in:
parent
8b87d179e9
commit
924a82c0b1
1 changed files with 36 additions and 0 deletions
36
surfsense_backend/app/automations/runtime/retries.py
Normal file
36
surfsense_backend/app/automations/runtime/retries.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
"""Retry policy enforcement for action handlers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Awaitable, Callable
|
||||
|
||||
|
||||
async def with_retries[T](
|
||||
coro_factory: Callable[[], Awaitable[T]],
|
||||
*,
|
||||
max_retries: int,
|
||||
backoff: str,
|
||||
timeout: int | None,
|
||||
) -> tuple[T, int]:
|
||||
"""Call ``coro_factory`` up to ``1 + max_retries`` times. Return ``(result, attempts)``."""
|
||||
total = 1 + max(0, max_retries)
|
||||
for attempt in range(1, total + 1):
|
||||
try:
|
||||
coro = coro_factory()
|
||||
if timeout is not None and timeout > 0:
|
||||
return await asyncio.wait_for(coro, timeout=timeout), attempt
|
||||
return await coro, attempt
|
||||
except Exception:
|
||||
if attempt >= total:
|
||||
raise
|
||||
await asyncio.sleep(_backoff_seconds(backoff, attempt))
|
||||
raise RuntimeError("with_retries exhausted without raising or returning")
|
||||
|
||||
|
||||
def _backoff_seconds(strategy: str, attempt: int) -> float:
|
||||
if strategy == "exponential":
|
||||
return float(2 ** (attempt - 1))
|
||||
if strategy == "linear":
|
||||
return float(attempt)
|
||||
return 0.0
|
||||
Loading…
Add table
Add a link
Reference in a new issue