35 lines
1.0 KiB
Python
35 lines
1.0 KiB
Python
"""Простой in-process rate limit для POST /api/admin/llm/* по логину сессии."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import time
|
|
from typing import MutableMapping
|
|
|
|
_LAST: MutableMapping[str, float] = {}
|
|
|
|
|
|
def reset_llm_rate_limit_for_tests() -> None:
|
|
_LAST.clear()
|
|
|
|
|
|
def llm_post_rate_allow(
|
|
login: str, interval_sec: float, *, bucket: str = "default"
|
|
) -> tuple[bool, float]:
|
|
"""
|
|
Возвращает (разрешено, сек_до_следующего_слота).
|
|
При interval_sec <= 0 ограничения нет.
|
|
|
|
bucket — отдельный счётчик на пользователя (например «chat» и «heavy» не мешают друг другу).
|
|
"""
|
|
login_k = (login or "").strip()
|
|
if interval_sec <= 0 or not login_k:
|
|
return True, 0.0
|
|
key = f"{login_k}\x00{bucket}"
|
|
now = time.monotonic()
|
|
last = _LAST.get(key, 0.0)
|
|
wait = interval_sec - (now - last)
|
|
if wait > 0:
|
|
return False, wait
|
|
_LAST[key] = now
|
|
return True, 0.0
|