Spaces:
Sleeping
Sleeping
File size: 3,938 Bytes
f202266 ab7ee83 f202266 ccbdc68 f202266 ccbdc68 f202266 ab7ee83 f202266 ab7ee83 f202266 ab7ee83 f202266 ccbdc68 f202266 ab7ee83 f202266 ab7ee83 f202266 ab7ee83 f202266 ccbdc68 ab7ee83 f202266 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
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):
@wraps(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
"""
@wraps(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 {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
|