kofdai's picture
Upload folder using huggingface_hub
594ed40 verified
import redis.asyncio as redis
import json
from typing import Optional, Any
import sys
import os
# Add project root to sys.path to allow importing hot_cache
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..')))
from backend.app.config import settings
from hot_cache import LRUCache
class CacheService:
"""
Cache service class using Redis with a fallback to in-memory cache.
"""
_client: Optional[redis.Redis] = None
_redis_unavailable: bool = False
_memory_cache: LRUCache = LRUCache(max_size=100)
async def _get_redis_client(self) -> Optional[redis.Redis]:
"""Initializes and returns a Redis client if available."""
if self._redis_unavailable:
return None
if self._client is None:
try:
print("--- Initializing Redis Client ---")
# Set a timeout to avoid long waits if Redis is not running
client = redis.from_url(
settings.REDIS_URL, socket_connect_timeout=1, encoding="utf-8", decode_responses=True
)
await client.ping()
self._client = client
print("--- Redis Client Initialized Successfully. Redis caching is active. ---")
except Exception as e:
print(f"--- Redis connection failed: {e}. Falling back to in-memory cache. ---")
self._redis_unavailable = True
self._client = None
return self._client
async def get(self, key: str) -> Optional[Any]:
"""Fetches a value from the cache by key."""
client = await self._get_redis_client()
if client:
try:
cached_value = await client.get(key)
if cached_value:
print(f"REDIS CACHE HIT for key: {key}")
return json.loads(cached_value)
except Exception as e:
print(f"Redis GET error: {e}. Disabling Redis for this session.")
self.__class__._redis_unavailable = True # Use class attribute to disable for all instances
self.__class__._client = None
# Fallback to in-memory cache
value = self._memory_cache.get(key)
if value:
print(f"MEMORY CACHE HIT for key: {key}")
return value
print(f"CACHE MISS for key: {key}")
return None
async def set(self, key: str, value: Any, ttl: int = 3600):
"""Sets a key-value pair in the cache with a TTL."""
client = await self._get_redis_client()
if client:
try:
value_to_cache = json.dumps(value, default=str)
await client.set(key, value_to_cache, ex=ttl)
print(f"REDIS CACHE SET for key: {key}")
return
except Exception as e:
print(f"Redis SET error: {e}. Disabling Redis for this session.")
self.__class__._redis_unavailable = True # Use class attribute to disable for all instances
self.__class__._client = None
# Fallback to in-memory cache
self._memory_cache[key] = value
print(f"MEMORY CACHE SET for key: {key}")
# --- Dependency Injection Function ---
async def get_cache_service() -> "CacheService":
"""
Factory function for dependency injection.
Returns an instance of the CacheService.
"""
return CacheService()