"""示例 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()