"""线程安全的取消令牌,用于 ETL 管道的优雅中断。""" from __future__ import annotations import threading class CancellationToken: """线程安全的取消令牌,封装 threading.Event。 支持手动取消和超时自动取消两种模式。 取消操作不可逆——一旦 cancel() 被调用,is_cancelled 永远为 True。 """ def __init__(self, timeout: float | None = None): """初始化取消令牌。 Args: timeout: 超时秒数。传入正数时启动守护定时器, 到期后自动调用 cancel()。None 或 <=0 不启动定时器。 """ self._event = threading.Event() self._timer: threading.Timer | None = None if timeout is not None and timeout > 0: self._timer = threading.Timer(timeout, self.cancel) self._timer.daemon = True self._timer.start() def cancel(self) -> None: """发出取消信号(幂等,可多次调用)。""" self._event.set() @property def is_cancelled(self) -> bool: """当前是否已取消。""" return self._event.is_set() @property def event(self) -> threading.Event: """底层 Event 对象,供 RateLimiter 等组件轮询使用。""" return self._event def dispose(self) -> None: """清理超时定时器,防止资源泄漏。 管道结束后应主动调用;即使不调用,守护线程也会随主进程退出。 """ if self._timer is not None: self._timer.cancel() self._timer = None