Files

87 lines
2.4 KiB
Python
Raw Permalink Normal View History

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