Files
xiaobai-review/xiaobai-datahub/datahub/governance/retry.py
T
3498dd7a4b feat(HEL-382): 搭建 datahub 底座和盘后正式数据链路
新增独立 xiaobai-datahub 服务(SQLite WAL、Tushare 盘后发布、/v1 契约和管理后台),不改现站页面与数据链路。

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-09-02 12:05:26 +08:00

36 lines
1.0 KiB
Python

from __future__ import annotations
import time
from collections.abc import Callable
from typing import TypeVar
T = TypeVar("T")
class RetryError(RuntimeError):
def __init__(self, message: str, attempts: int, last_error: BaseException | None = None) -> None:
super().__init__(message)
self.attempts = attempts
self.last_error = last_error
def retry_call(
fn: Callable[[], T],
attempts: int = 5,
base_delay: float = 0.2,
max_delay: float = 8.0,
sleeper: Callable[[float], None] = time.sleep,
retry_on: tuple[type[BaseException], ...] = (Exception,),
) -> T:
last: BaseException | None = None
for attempt in range(1, max(1, attempts) + 1):
try:
return fn()
except retry_on as exc:
last = exc
if attempt >= attempts:
break
delay = min(max_delay, base_delay * (2 ** (attempt - 1)))
sleeper(delay)
raise RetryError(f"retry exhausted after {attempts} attempts: {last}", attempts, last)