Files
group_xinghuo_jinrong/app/service/risk/redis_gateway.py
T

69 lines
2.1 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 单例网关(B7 lifespan 管理连接):预警广播 publish + L3 缓存失效 DEL。
惰性连接(首次 publish/DEL 才建);连接/执行失败一律降级日志,不阻塞业务
(DB 为权威,PRD FR-4 通知语义)。测试注入 fake:monkeypatch 本模块
`_gateway`,实现 publish(channel, payload) / delete(*keys) 即可。
"""
from __future__ import annotations
import json
import logging
from typing import Any
from app.config.settings import settings
logger = logging.getLogger(__name__)
class RedisGateway:
def __init__(self, url: str | None = None) -> None:
self._url = url or settings.redis_url
self._client: Any = None
def _ensure(self) -> Any:
if self._client is None:
import redis
self._client = redis.Redis.from_url(self._url, decode_responses=True)
return self._client
def publish(self, channel: str, payload: dict[str, Any]) -> None:
self._ensure().publish(channel, json.dumps(payload, ensure_ascii=False))
def delete(self, *keys: str) -> None:
self._ensure().delete(*keys)
_gateway: RedisGateway | Any | None = None
def set_gateway(gateway: RedisGateway | Any | None) -> None:
"""单例注入点(B7 lifespan 注册;测试注入 fake)。"""
global _gateway
_gateway = gateway
def get_gateway() -> RedisGateway:
"""取网关单例;未注册时惰性创建(脚本直调场景)。"""
global _gateway
if _gateway is None:
_gateway = RedisGateway()
return _gateway
def publish(channel: str, payload: dict[str, Any]) -> None:
"""广播;失败降级(不阻塞预警落库)。"""
try:
get_gateway().publish(channel, payload)
except Exception:
logger.exception("publish %s failed", channel)
def cache_delete(*keys: str) -> None:
"""写侧缓存失效(PRD §5.1:MySQL 更新时 DEL);失败降级(TTL 兜底过期)。"""
try:
get_gateway().delete(*keys)
except Exception:
logger.warning("cache DEL failed (degrade to TTL): %s", keys, exc_info=True)