44 lines
1.5 KiB
Python
44 lines
1.5 KiB
Python
"""请求间隔控制器,支持取消信号中断等待。"""
|
||
|
||
import random
|
||
import time
|
||
import threading
|
||
|
||
|
||
class RateLimiter:
|
||
"""请求间隔控制器,在相邻 API 请求之间插入随机等待时间,防止触发上游风控。
|
||
|
||
等待期间以 0.5s 为单位轮询 cancel_event,支持快速响应取消信号。
|
||
"""
|
||
|
||
def __init__(self, min_interval: float = 5.0, max_interval: float = 20.0):
|
||
if min_interval > max_interval:
|
||
raise ValueError(
|
||
f"min_interval({min_interval}) 不能大于 max_interval({max_interval})"
|
||
)
|
||
self._min = min_interval
|
||
self._max = max_interval
|
||
self._last_interval: float = 0.0
|
||
|
||
def wait(self, cancel_event: threading.Event | None = None) -> bool:
|
||
"""等待随机间隔。返回 False 表示被取消信号中断。
|
||
|
||
将等待时间拆分为 0.5s 小段,每段检查 cancel_event,
|
||
以便在取消信号到达时快速退出(最多延迟 0.5s)。
|
||
"""
|
||
interval = random.uniform(self._min, self._max)
|
||
self._last_interval = interval
|
||
remaining = interval
|
||
while remaining > 0:
|
||
if cancel_event and cancel_event.is_set():
|
||
return False
|
||
sleep_time = min(0.5, remaining)
|
||
time.sleep(sleep_time)
|
||
remaining -= sleep_time
|
||
return True
|
||
|
||
@property
|
||
def last_interval(self) -> float:
|
||
"""最近一次 wait() 生成的随机间隔值。"""
|
||
return self._last_interval
|