| """
|
| Redis Cache Manager using Upstash
|
| Handles session caching and user data caching
|
| """
|
| import os
|
| import json
|
| from typing import Optional, Dict, Any
|
| from dotenv import load_dotenv
|
| from upstash_redis import Redis
|
|
|
|
|
| load_dotenv()
|
|
|
| class CacheManager:
|
| def __init__(self):
|
| """Initialize Upstash Redis client"""
|
| redis_url = os.getenv("UPSTASH_REDIS_REST_URL")
|
| redis_token = os.getenv("UPSTASH_REDIS_REST_TOKEN")
|
|
|
| if redis_url and redis_token:
|
| self.redis = Redis(url=redis_url, token=redis_token)
|
| self.enabled = True
|
| print("✅ Redis cache enabled (Upstash)")
|
| else:
|
| self.redis = None
|
| self.enabled = False
|
| print("⚠️ Redis cache disabled (no credentials)")
|
|
|
| def get(self, key: str) -> Optional[Any]:
|
| """Get value from cache"""
|
| if not self.enabled:
|
| return None
|
|
|
| try:
|
| data = self.redis.get(key)
|
| if data:
|
| return json.loads(data) if isinstance(data, str) else data
|
| return None
|
| except Exception as e:
|
| print(f"Cache get error: {e}")
|
| return None
|
|
|
| def set(self, key: str, value: Any, ttl: int = 3600):
|
| """Set value in cache with TTL (default 1 hour)"""
|
| if not self.enabled:
|
| return False
|
|
|
| try:
|
| serialized = json.dumps(value) if not isinstance(value, str) else value
|
| self.redis.setex(key, ttl, serialized)
|
| return True
|
| except Exception as e:
|
| print(f"Cache set error: {e}")
|
| return False
|
|
|
| def delete(self, key: str):
|
| """Delete key from cache"""
|
| if not self.enabled:
|
| return False
|
|
|
| try:
|
| self.redis.delete(key)
|
| return True
|
| except Exception as e:
|
| print(f"Cache delete error: {e}")
|
| return False
|
|
|
| def get_or_fetch(self, key: str, fetch_fn, ttl: int = 3600):
|
| """Get from cache or fetch and cache"""
|
|
|
| cached = self.get(key)
|
| if cached is not None:
|
| print(f"✅ Cache HIT: {key}")
|
| return cached
|
|
|
|
|
| print(f"❌ Cache MISS: {key}")
|
| data = fetch_fn()
|
|
|
|
|
| if data is not None:
|
| self.set(key, data, ttl)
|
|
|
| return data
|
|
|
|
|
| cache = CacheManager()
|
|
|