""" cache_endpoints.py — Endpoint API per Gestione Cache Endpoint: GET /api/cache/stats — Statistiche cache POST /api/cache/invalidate — Invalida un entry GET /api/cache/health — Health check cache POST /api/cache/reset-stats — Resetta statistiche """ from fastapi import APIRouter, HTTPException from pydantic import BaseModel from typing import Optional import logging # Import cache manager try: from backend.api.cache_manager import ( get_cache_stats, reset_cache_stats, invalidate_cache, CacheStrategy, CACHE_ENABLED, ) except ImportError: from cache_manager import ( get_cache_stats, reset_cache_stats, invalidate_cache, CacheStrategy, CACHE_ENABLED, ) _logger = logging.getLogger("cache_endpoints") router = APIRouter(prefix="/api/cache", tags=["cache"]) # ── Modelli Pydantic ────────────────────────────────────────────────────── class InvalidateCacheRequest(BaseModel): strategy: str # "query", "memory", "embedding", "conversation", "analytics" identifier: str class CacheStatsResponse(BaseModel): enabled: bool hits: int misses: int sets: int deletes: int evictions: int hit_rate_percent: float total_requests: int class CacheHealthResponse(BaseModel): ok: bool cache_enabled: bool message: str # ── Endpoint: Statistiche Cache ──────────────────────────────────────────── @router.get("/stats", response_model=CacheStatsResponse) async def cache_stats(): """Ritorna le statistiche del cache layer.""" try: stats = get_cache_stats() return CacheStatsResponse(**stats) except Exception as exc: _logger.error(f"Error fetching cache stats: {exc}") raise HTTPException(500, "Error fetching cache stats") # ── Endpoint: Invalida Cache ────────────────────────────────────────────── @router.post("/invalidate") async def invalidate_cache_entry(req: InvalidateCacheRequest): """Invalida un entry specifico dalla cache.""" try: # Valida strategy try: strategy = CacheStrategy(req.strategy) except ValueError: raise HTTPException( 400, f"Invalid strategy. Must be one of: {', '.join([s.value for s in CacheStrategy])}", ) # Invalida success = await invalidate_cache(strategy, req.identifier) return { "ok": success, "strategy": req.strategy, "identifier": req.identifier, "message": "Cache entry invalidated" if success else "Failed to invalidate cache entry", } except HTTPException: raise except Exception as exc: _logger.error(f"Error invalidating cache: {exc}") raise HTTPException(500, "Error invalidating cache") # ── Endpoint: Health Check ──────────────────────────────────────────────── @router.get("/health", response_model=CacheHealthResponse) async def cache_health(): """Health check per il cache layer.""" try: stats = get_cache_stats() return CacheHealthResponse( ok=True, cache_enabled=CACHE_ENABLED, message=f"Cache layer operational. Hit rate: {stats.get('hit_rate_percent', 0):.1f}%", ) except Exception as exc: _logger.error(f"Cache health check failed: {exc}") return CacheHealthResponse( ok=False, cache_enabled=CACHE_ENABLED, message=f"Cache health check failed: {str(exc)}", ) # ── Endpoint: Reset Statistiche ─────────────────────────────────────────── @router.post("/reset-stats") async def reset_stats(): """Resetta le statistiche del cache.""" try: reset_cache_stats() return { "ok": True, "message": "Cache statistics reset", } except Exception as exc: _logger.error(f"Error resetting cache stats: {exc}") raise HTTPException(500, "Error resetting cache stats") # ── Endpoint: Info Cache ────────────────────────────────────────────────── @router.get("/info") async def cache_info(): """Ritorna informazioni sulla configurazione del cache.""" try: from cache_manager import ( CACHE_ENABLED, CACHE_TTL_DEFAULT, CACHE_MAX_SIZE, CACHE_TTL_BY_STRATEGY, SUPABASE_A_URL, SUPABASE_B_URL, ) return { "enabled": CACHE_ENABLED, "ttl_default_seconds": CACHE_TTL_DEFAULT, "max_size": CACHE_MAX_SIZE, "ttl_by_strategy": {k.value: v for k, v in CACHE_TTL_BY_STRATEGY.items()}, "supabase_a_configured": bool(SUPABASE_A_URL), "supabase_b_configured": bool(SUPABASE_B_URL), } except Exception as exc: _logger.error(f"Error fetching cache info: {exc}") raise HTTPException(500, "Error fetching cache info")