Spaces:
Sleeping
Sleeping
| import redis | |
| import json | |
| from typing import Optional, Any | |
| from src.config import REDIS_URL, CACHE_TTL | |
| from src.utils import setup_logger | |
| logger = setup_logger(__name__) | |
| class CacheManager: | |
| _instance = None | |
| def __new__(cls): | |
| if cls._instance is None: | |
| cls._instance = super(CacheManager, cls).__new__(cls) | |
| cls._instance._initialize() | |
| return cls._instance | |
| def _initialize(self): | |
| """Initialize Redis connection.""" | |
| try: | |
| self.client = redis.from_url(REDIS_URL, decode_responses=True) | |
| # Test connection | |
| self.client.ping() | |
| self.enabled = True | |
| logger.info(f"Redis cache initialized successfully: {REDIS_URL}") | |
| except redis.ConnectionError as e: | |
| self.enabled = False | |
| logger.warning(f"Redis cache initialization failed: {e}. Caching disabled.") | |
| except Exception as e: | |
| self.enabled = False | |
| logger.warning(f"Unexpected Redis error: {e}. Caching disabled.") | |
| def get(self, key: str) -> Optional[Any]: | |
| """Retrieve value from cache.""" | |
| if not self.enabled: | |
| return None | |
| try: | |
| val = self.client.get(key) | |
| if val: | |
| logger.debug(f"Cache HIT for key: {key}") | |
| return json.loads(val) | |
| except Exception as e: | |
| logger.error(f"Error getting from cache: {e}") | |
| return None | |
| def set(self, key: str, value: Any, ttl: int = CACHE_TTL) -> bool: | |
| """Set value in cache with TTL.""" | |
| if not self.enabled: | |
| return False | |
| try: | |
| self.client.setex(key, ttl, json.dumps(value)) | |
| return True | |
| except Exception as e: | |
| logger.error(f"Error setting cache: {e}") | |
| return False | |
| def generate_key(self, prefix: str, **kwargs) -> str: | |
| """Generate a consistent cache key from arguments.""" | |
| sorted_kwargs = dict(sorted(kwargs.items())) | |
| key_part = "_".join([f"{k}:{v}" for k, v in sorted_kwargs.items()]) | |
| return f"{prefix}:{key_part}" | |