Files
chongming-utils-task/examples/03_retry_and_timeout.py
T
chakcy f4de43c743 初始提交:chongming-task 任务控制库
单任务受控执行(15 态状态机 + 审计轨迹)、DAG 管道、Controller 门面。
执行器三个:线程(默认,含 async def 任务)、内联(同步 / 测试)、进程
(spawn 子进程:硬性停止、绕开 GIL、崩溃隔离)。
调度:并发额度 + 每桶限流 + 具名资源信号量(按标签)+ 优先级排队。
持久层:TaskStore 契约 + 内存 / SQLite / Postgres 实现,契约测试随包发布。
跨进程与多节点:写穿 / 读穿、指令通道与租约、owned_buckets 划界、reconcile。
CLI、12 个可直接运行的示例、docs/ 下 5 份文档。

门禁:ruff / ruff format / mypy(strict) 干净;
      pytest 563 passed(44 skipped 是需要真实 Postgres 的那批);
      带一台可连的 Postgres 时 607 passed。
2026-10-08 23:47:50 +08:00

87 lines
2.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""示例 3:重试与超时。
运行::
uv run python examples/03_retry_and_timeout.py
"""
from __future__ import annotations
import time
from chongming_task.policies import ExponentialBackoff, RetryPolicy, Timeout
from chongming_task.run import run_task
_attempts = 0
def flaky(ctx, succeed_on_attempt: int) -> str:
"""前几次故意失败,用来演示重试与退避。"""
global _attempts
_attempts += 1
if _attempts < succeed_on_attempt:
raise RuntimeError(f"第 {_attempts} 次尝试遇到暂时性故障")
return f"第 {_attempts} 次尝试成功"
def slow(ctx) -> str:
"""跑得很慢,用来演示超时后会被请求停止。"""
for _ in range(10_000):
ctx.checkpoint()
time.sleep(0.01)
return "跑完了"
def demo_retry() -> None:
print("== 重试:失败两次后成功 ==")
_attempts = 0
outcome = run_task(
flaky,
3,
retry=RetryPolicy(max_attempts=5, backoff=ExponentialBackoff(base=0.05, factor=2)),
task_id="demo-retry",
name="会抖的任务",
)
print(f" 终态 :{outcome.status.value}")
print(f" 返回值 :{outcome.value}")
print(f" 尝试次数 :{outcome.snapshot.attempt}/{outcome.snapshot.max_attempts}")
def demo_retry_exhausted() -> None:
print("\n== 重试:预算耗尽 ==")
global _attempts
_attempts = 0
outcome = run_task(
flaky,
99, # 永远不会成功
retry=RetryPolicy(max_attempts=2, backoff=ExponentialBackoff(base=0.05, factor=1)),
task_id="demo-exhausted",
name="必定失败",
)
print(f" 终态 :{outcome.status.value}")
print(f" 尝试次数 :{outcome.snapshot.attempt}/{outcome.snapshot.max_attempts}")
print(f" 失败归类 :{outcome.failure.kind.value if outcome.failure else '-'}")
def demo_timeout() -> None:
print("\n== 超时:单次尝试不超过 0.5 秒 ==")
outcome = run_task(
slow,
timeout=Timeout(per_attempt=0.5),
task_id="demo-timeout",
name="慢任务",
)
print(f" 终态 :{outcome.status.value}")
print(f" 失败归类 :{outcome.failure.kind.value if outcome.failure else '-'}")
print(f" 可重试 :{outcome.failure.retryable if outcome.failure else '-'}")
def main() -> None:
demo_retry()
demo_retry_exhausted()
demo_timeout()
if __name__ == "__main__":
main()