generated from kgod/ai-review-template
自内部仓库剥离深度优化与 RAG 知识库后的交付版本: - Builder 对话式简历生成(FSM + 意图路由 LLM 兜底增强) - 条目级轻度优化:事实覆盖门禁 + STAR/bullet 修复链,功能/简介/成果与技术栈同级保护 - 简历导入:DOCX/PDF 解析、结构归一、手机号脱敏 - PostgreSQL 运行时 + Alembic 迁移链 Co-Authored-By: Claude <noreply@anthropic.com>
38 lines
1.1 KiB
Python
38 lines
1.1 KiB
Python
"""In-process sliding-window rate limiting for single-process deployments."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
from collections import deque
|
|
from typing import Callable
|
|
|
|
|
|
class SlidingWindowRateLimiter:
|
|
"""Allow at most ``limit`` requests per key during a sliding time window."""
|
|
|
|
def __init__(
|
|
self,
|
|
*,
|
|
limit: int,
|
|
window_seconds: float,
|
|
clock: Callable[[], float] = time.monotonic,
|
|
) -> None:
|
|
if limit < 1:
|
|
raise ValueError("limit must be positive")
|
|
if window_seconds <= 0:
|
|
raise ValueError("window_seconds must be positive")
|
|
self.limit = limit
|
|
self.window_seconds = window_seconds
|
|
self.clock = clock
|
|
self._hits: dict[str, deque[float]] = {}
|
|
|
|
def allow(self, key: str) -> bool:
|
|
now = self.clock()
|
|
hits = self._hits.setdefault(key, deque())
|
|
while hits and now - hits[0] >= self.window_seconds:
|
|
hits.popleft()
|
|
if len(hits) >= self.limit:
|
|
return False
|
|
hits.append(now)
|
|
return True
|