Files
video/server/build/lib/app/core/ratelimit.py
T
2026-10-16 13:51:00 +08:00

34 lines
1.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""接口限流:Redis 固定窗口计数(Nginx 层之外的第二道,对齐《02-技术文档》4.5)"""
from datetime import datetime
import redis.asyncio as aioredis
from app.core import errors
from app.core.response import BizException
async def hit(redis: aioredis.Redis, key: str, limit: int, window_seconds: int, message: str | None = None) -> None:
"""固定窗口计数,超限抛 1005(HTTP 429)。key 需自带维度与窗口标识。"""
n = await redis.incr(key)
if n == 1:
await redis.expire(key, window_seconds)
if n > limit:
raise BizException(errors.RATE_LIMITED, message, http_status=429)
def window_key(window_seconds: int) -> str:
"""窗口标识:分钟 %Y%m%d%H%M / 小时 %Y%m%d%H / 天 %Y%m%d"""
now = datetime.now()
if window_seconds >= 86400:
return f"{now:%Y%m%d}"
if window_seconds >= 3600:
return f"{now:%Y%m%d%H}"
return f"{now:%Y%m%d%H%M}"
async def hit_subject(
redis: aioredis.Redis, subject: str, action: str, limit: int, window_seconds: int, message: str | None = None
) -> None:
"""按主体(用户ID/设备ID/IP)+ 动作限流:rl:{action}:{subject}:{窗口}"""
await hit(redis, f"rl:{action}:{subject}:{window_key(window_seconds)}", limit, window_seconds, message)