"""Redis 缓存工具类 — 管理会计OS""" import json import hashlib import logging from typing import Any, Optional logger = logging.getLogger("cma.cache") try: import redis as redis_lib _client = redis_lib.Redis( host="127.0.0.1", port=6379, db=1, decode_responses=True, socket_connect_timeout=2, socket_timeout=3, ) _client.ping() _available = True logger.info("Redis 缓存已连接 (db=1)") except Exception as e: _client = None _available = False logger.warning(f"Redis 不可用,回退到无缓存模式: {e}") def _make_key(module: str, key: str) -> str: """生成统一格式的缓存key: cma:cache:{module}:{hash}""" h = hashlib.md5(key.encode()).hexdigest()[:16] return f"cma:cache:{module}:{h}" def get(module: str, key: str) -> Optional[Any]: """获取缓存""" if not _available: return None try: full_key = _make_key(module, key) data = _client.get(full_key) if data: return json.loads(data) return None except Exception as e: logger.warning(f"缓存读取失败 [{module}]: {e}") return None def set(module: str, key: str, value: Any, ttl_seconds: int = 300) -> bool: """写入缓存,默认5分钟""" if not _available: return False try: full_key = _make_key(module, key) _client.setex(full_key, ttl_seconds, json.dumps(value, ensure_ascii=False)) return True except Exception as e: logger.warning(f"缓存写入失败 [{module}]: {e}") return False def delete(module: str, key: str = None) -> bool: """删除缓存。不传key则清空该模块所有缓存""" if not _available: return False try: if key: full_key = _make_key(module, key) _client.delete(full_key) else: pattern = f"cma:cache:{module}:*" cursor = 0 while True: cursor, keys = _client.scan(cursor=cursor, match=pattern, count=100) if keys: _client.delete(*keys) if cursor == 0: break return True except Exception as e: logger.warning(f"缓存删除失败 [{module}]: {e}") return False def clear_all() -> bool: """清空所有CMA缓存""" if not _available: return False try: cursor = 0 while True: cursor, keys = _client.scan(cursor=cursor, match="cma:cache:*", count=200) if keys: _client.delete(*keys) if cursor == 0: break return True except Exception as e: logger.warning(f"缓存清空失败: {e}") return False