Spaces:
Sleeping
Sleeping
| import json | |
| from functools import wraps | |
| from services.config.valkey_config import get_redis_client, is_connection_available | |
| import time | |
| redis_client = get_redis_client() | |
| def cache_data(key_prefix, expire_time=3600): | |
| """ | |
| A decorator that caches the result of a function in Valkey. | |
| Args: | |
| key_prefix (str): Prefix for the Valkey key | |
| expire_time (int): Time in seconds for the cache to expire (default: 1 hour) | |
| """ | |
| def decorator(func): | |
| async def wrapper(*args, **kwargs): | |
| # If Valkey is not available, execute function directly | |
| if not is_connection_available() or not redis_client: | |
| print(f"Cache DISABLED for {key_prefix} - executing function directly") | |
| return await func(*args, **kwargs) | |
| try: | |
| # Create a unique key based on the function arguments | |
| cache_key = f"{key_prefix}:{str(args)}:{str(kwargs)}" | |
| # Try to get the cached result | |
| cached_result = redis_client.get(cache_key) | |
| if cached_result: | |
| print(f"Cache HIT: {cache_key}") | |
| return json.loads(cached_result) | |
| # If not cached, execute the function | |
| print(f"Cache MISS: {cache_key}") | |
| result = await func(*args, **kwargs) | |
| # Cache the result | |
| redis_client.setex( | |
| cache_key, | |
| expire_time, | |
| json.dumps(result) | |
| ) | |
| return result | |
| except Exception as e: | |
| print(f"Cache ERROR for {key_prefix}: {e}") | |
| print("Falling back to direct function execution") | |
| return await func(*args, **kwargs) | |
| return wrapper | |
| return decorator | |
| def clear_cache(pattern="*"): | |
| """ | |
| Clear cache entries matching the given pattern | |
| """ | |
| if not is_connection_available() or not redis_client: | |
| print("Cache DISABLED: Cannot clear cache") | |
| return | |
| try: | |
| cursor = 0 | |
| while True: | |
| cursor, keys = redis_client.scan(cursor, match=pattern) | |
| if keys: | |
| redis_client.delete(*keys) | |
| if cursor == 0: | |
| break | |
| print(f"Cache cleared for pattern: {pattern}") | |
| except Exception as e: | |
| print(f"Cache clear ERROR: {e}") | |
| def cache_with_fallback(func): | |
| """ | |
| A decorator that implements cache with fallback mechanism | |
| If Valkey is unavailable, it will execute the function directly | |
| """ | |
| async def wrapper(*args, **kwargs): | |
| # If Valkey is not available, execute function directly | |
| if not is_connection_available() or not redis_client: | |
| print(f"Cache DISABLED for {func.__name__} - executing function directly") | |
| return await func(*args, **kwargs) | |
| cache_key = f"{func.__name__}:{str(args)}:{str(kwargs)}" | |
| try: | |
| # Try to get from cache | |
| cached_result = redis_client.get(cache_key) | |
| if cached_result: | |
| print(f"Cache HIT: {cache_key}") | |
| return json.loads(cached_result) | |
| # If not in cache, execute function | |
| print(f"Cache MISS: {cache_key}") | |
| result = await func(*args, **kwargs) | |
| # Cache the result | |
| redis_client.setex( | |
| cache_key, | |
| 3600, # 1 hour default | |
| json.dumps(result) | |
| ) | |
| return result | |
| except Exception as e: | |
| # If Valkey fails, execute function directly | |
| print(f"Cache error for {func.__name__}: {str(e)}, executing function directly") | |
| return await func(*args, **kwargs) | |
| return wrapper | |