74 lines
1.9 KiB
Python
74 lines
1.9 KiB
Python
"""Redis 连接池 + 缓存读写封装
|
||
|
||
用于 verify-token 的服务/Token 缓存,减少数据库访问。
|
||
缓存 Key 约定:
|
||
mcp:svc:{api_key_hash} → 服务信息(TTL 120s)
|
||
mcp:tok:{token_hash} → Token 信息(TTL 30s)
|
||
mcp:tok:miss:{token_hash} → 无效标记,防穿透(TTL 30s)
|
||
"""
|
||
|
||
import json
|
||
|
||
import redis.asyncio as aioredis
|
||
|
||
from .config import settings
|
||
|
||
_pool: aioredis.Redis | None = None
|
||
|
||
|
||
async def get_redis() -> aioredis.Redis:
|
||
"""获取 Redis 连接(进程级单例)。"""
|
||
global _pool
|
||
if _pool is None:
|
||
_pool = aioredis.Redis(
|
||
host=settings.REDIS_HOST,
|
||
port=settings.REDIS_PORT,
|
||
db=settings.REDIS_DB,
|
||
password=settings.REDIS_PASSWORD,
|
||
decode_responses=True,
|
||
)
|
||
return _pool
|
||
|
||
|
||
async def close_redis() -> None:
|
||
"""关闭 Redis 连接(进程退出时调用)。"""
|
||
global _pool
|
||
if _pool is not None:
|
||
await _pool.aclose()
|
||
_pool = None
|
||
|
||
|
||
async def cache_get(key: str) -> dict | None:
|
||
"""读取 JSON 缓存,返回 dict 或 None。Redis 不可用时返回 None(视为缓存未命中)。"""
|
||
try:
|
||
r = await get_redis()
|
||
raw = await r.get(key)
|
||
except Exception:
|
||
return None
|
||
if raw is None:
|
||
return None
|
||
try:
|
||
return json.loads(raw)
|
||
except Exception:
|
||
return None
|
||
|
||
|
||
async def cache_set(key: str, value: dict, ttl: int) -> None:
|
||
"""写入 JSON 缓存,带 TTL(秒)。Redis 不可用时静默跳过。"""
|
||
try:
|
||
r = await get_redis()
|
||
await r.setex(key, ttl, json.dumps(value))
|
||
except Exception:
|
||
pass
|
||
|
||
|
||
async def cache_delete(*keys: str) -> None:
|
||
"""删除缓存 key。Redis 不可用时静默跳过,缓存会自然过期。"""
|
||
if not keys:
|
||
return
|
||
try:
|
||
r = await get_redis()
|
||
await r.delete(*keys)
|
||
except Exception:
|
||
pass
|