Files
socweb/backend/app/cache/redis.py
T
gongzhiyongandClaude Opus 4.6 3759ecd1a6 feat(backend): Phase 3 - Jina search + Redis cache
- Add web_search tool with Jina Search/Reader/Rerank
- Flash mode: top 3, 8s timeout, no Reader/Rerank
- Pro mode: top 10, 20s timeout, concurrent Reader + Rerank top 5
- Add Redis async cache (TTL=300s) for search results
- Register "search" in ALL_TOOLS mapping

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:39:43 +08:00

74 lines
2.0 KiB
Python

"""Redis cache client for search result caching.
Uses Azure Redis (TLS on port 6380).
Cache key pattern: search:{query_hash}:{model}
TTL: 300 seconds (5 minutes).
"""
from __future__ import annotations
import hashlib
import logging
import redis.asyncio as redis
from app.config import settings
logger = logging.getLogger(__name__)
_pool: redis.Redis | None = None
CACHE_TTL = 300 # seconds
async def get_redis() -> redis.Redis:
"""Return a singleton async Redis client."""
global _pool
if _pool is None:
_pool = redis.from_url(
settings.redis_url,
decode_responses=True,
socket_connect_timeout=5,
socket_timeout=5,
)
return _pool
async def close_redis() -> None:
"""Close the Redis connection pool (for clean shutdown)."""
global _pool
if _pool is not None:
await _pool.aclose()
_pool = None
def _cache_key(query: str, model: str) -> str:
"""Build a cache key from query hash and model."""
query_hash = hashlib.sha256(query.strip().lower().encode("utf-8")).hexdigest()[:16]
return f"search:{query_hash}:{model}"
async def get_cached_search(query: str, model: str) -> str | None:
"""Look up a cached search result. Returns None on miss or error."""
try:
r = await get_redis()
key = _cache_key(query, model)
value = await r.get(key)
if value is not None:
logger.info("Cache HIT for key=%s", key)
return value
except Exception:
logger.warning("Redis GET failed, treating as cache miss", exc_info=True)
return None
async def set_cached_search(query: str, model: str, result: str) -> None:
"""Store a search result in cache with TTL."""
try:
r = await get_redis()
key = _cache_key(query, model)
await r.set(key, result, ex=CACHE_TTL)
logger.info("Cache SET key=%s ttl=%ds", key, CACHE_TTL)
except Exception:
logger.warning("Redis SET failed, result not cached", exc_info=True)