70 lines
2.4 KiB
Python
70 lines
2.4 KiB
Python
|
|
"""指数退避计算工具。
|
|||
|
|
|
|||
|
|
本模块提供两个函数:
|
|||
|
|
|
|||
|
|
- ``calc_backoff_seconds``:根据连续错误数从退避序列取退避秒数。
|
|||
|
|
- ``calc_backoff_next_run_at``:计算退避后的下次运行时间。
|
|||
|
|
|
|||
|
|
设计要点(见设计方案 §8.2):
|
|||
|
|
|
|||
|
|
- 退避序列由配置 ``scheduler_backoff_schedule`` 提供(如 ``[10, 30, 120, 600, 3600]``)。
|
|||
|
|
- 根据 ``consecutive_errors`` 从序列取值,超过序列长度时取最后一个值。
|
|||
|
|
- ``consecutive_errors`` 为 0 时返回 0(无退避)。
|
|||
|
|
- 时间计算基于 ``utc_now_naive()``,结果为 UTC naive datetime。
|
|||
|
|
- 纯函数,不依赖框架层组件。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
from __future__ import annotations
|
|||
|
|
|
|||
|
|
from datetime import datetime, timedelta
|
|||
|
|
|
|||
|
|
from yuxi.utils.datetime_utils import utc_now_naive
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calc_backoff_seconds(consecutive_errors: int, schedule: list[int]) -> int:
|
|||
|
|
"""根据连续错误数计算退避秒数。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
consecutive_errors: 连续错误次数。
|
|||
|
|
schedule: 退避时间表(秒),如 ``[60, 300, 1800, 7200]``。
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
退避秒数,超过 ``schedule`` 长度时取最后一个值。
|
|||
|
|
|
|||
|
|
说明:
|
|||
|
|
- ``consecutive_errors <= 0`` 时返回 0(无退避)。
|
|||
|
|
- ``consecutive_errors`` 在 ``[1, len(schedule)]`` 范围内时,取
|
|||
|
|
``schedule[consecutive_errors - 1]``。
|
|||
|
|
- ``consecutive_errors`` 超过序列长度时,取 ``schedule[-1]``(封顶)。
|
|||
|
|
- ``schedule`` 为空时返回 0。
|
|||
|
|
"""
|
|||
|
|
if consecutive_errors <= 0 or not schedule:
|
|||
|
|
return 0
|
|||
|
|
index = min(consecutive_errors, len(schedule)) - 1
|
|||
|
|
return schedule[index]
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calc_backoff_next_run_at(
|
|||
|
|
consecutive_errors: int,
|
|||
|
|
schedule: list[int],
|
|||
|
|
*,
|
|||
|
|
base_time: datetime | None = None,
|
|||
|
|
) -> datetime:
|
|||
|
|
"""计算退避后的下次运行时间。
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
consecutive_errors: 连续错误次数。
|
|||
|
|
schedule: 退避时间表(秒)。
|
|||
|
|
base_time: 基准时间(UTC naive),默认 ``utc_now_naive()``。
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
UTC naive datetime,退避后的下次运行时间。
|
|||
|
|
|
|||
|
|
说明:
|
|||
|
|
``consecutive_errors`` 为 0 时退避秒数为 0,返回 ``base_time``
|
|||
|
|
(或当前 UTC 时间)。
|
|||
|
|
"""
|
|||
|
|
base = base_time if base_time is not None else utc_now_naive()
|
|||
|
|
seconds = calc_backoff_seconds(consecutive_errors, schedule)
|
|||
|
|
return base + timedelta(seconds=seconds)
|