feat(limits): 限流器过期键周期清扫(内存上限铁律)
LoginLimiter._fails 与 rate_limit._buckets 只增不删——懒清理只覆盖被 回访的键,扫号换 IP/设备轮换产生的键永不被回访 → 进程长跑缓慢累积。 两处各加 sweep()(全表清「全部时间戳均已出窗」的键,窗沿 <= 与既有 保留判据 t > now - W 同沿),main.lifespan 起周期任务(300s loop) 启动创建/关停取消(cancel 后 await 落地,不留 pending task)。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -213,6 +213,19 @@ class LoginLimiter:
|
||||
else:
|
||||
self._fails.pop(key, None)
|
||||
|
||||
def sweep(self, now: float | None = None) -> int:
|
||||
"""清扫过期键(spec 2026-10-19 §7——内存上限铁律):删「全部时间戳
|
||||
均已出窗」的键,返回清除数。与 _prune 的单键懒清理互补——allow/
|
||||
record_fail 只顺手清被回访的键,失败一次即消失的键(扫号换 IP/
|
||||
用户名)永不被回访,靠本方法全表兜底;由 main.lifespan 周期任务
|
||||
调用。时间戳按记录序追加,ts[-1] 即最新——最新出窗则全键出窗。"""
|
||||
now = time.time() if now is None else now
|
||||
dead = [k for k, ts in self._fails.items()
|
||||
if not ts or ts[-1] <= now - self.window_seconds]
|
||||
for k in dead:
|
||||
del self._fails[k]
|
||||
return len(dead)
|
||||
|
||||
|
||||
# 模块级单例: 路由与依赖共用同一份进程内存态(同 rate_limit._buckets 模式)
|
||||
token_store = TokenStore()
|
||||
|
||||
Reference in New Issue
Block a user