Spaces:
Sleeping
Sleeping
| import redis | |
| import hashlib | |
| import json | |
| import os | |
| from logger import get_logger | |
| logger = get_logger("cache") | |
| def get_redis_client(): | |
| url = os.environ.get("REDIS_URL") | |
| if not url: | |
| return None | |
| try: | |
| client = redis.from_url(url, decode_responses=True, socket_timeout=2) | |
| client.ping() | |
| return client | |
| except Exception as e: | |
| logger.warning("Redis unavailable", extra={"event": "cache_unavailable", "error": str(e)}) | |
| return None | |
| r = get_redis_client() | |
| CACHE_TTL = 3600 | |
| def make_cache_key(message: str, thread_id: str = "global") -> str: | |
| normalized = message.lower().strip() | |
| return "agent:v1:" + hashlib.sha256(f"{thread_id}:{normalized}".encode()).hexdigest() | |
| def get_cached_response(message: str, thread_id: str = "global") -> dict | None: | |
| if r is None: | |
| return None | |
| try: | |
| key = make_cache_key(message, thread_id) | |
| value = r.get(key) | |
| if value: | |
| logger.info("Cache hit", extra={"event": "cache_hit"}) | |
| return json.loads(value) | |
| return None | |
| except Exception as e: | |
| logger.warning("Cache get failed", extra={"event": "cache_error", "error": str(e)}) | |
| return None | |
| def set_cached_response(message: str, response: dict, thread_id: str = "global") -> None: | |
| if r is None: | |
| return | |
| try: | |
| key = make_cache_key(message, thread_id) | |
| r.setex(key, CACHE_TTL, json.dumps(response)) | |
| logger.info("Cache set", extra={"event": "cache_set"}) | |
| except Exception as e: | |
| logger.warning("Cache set failed", extra={"event": "cache_error", "error": str(e)}) | |
| # --- Tool-level caching --- | |
| TOOL_CACHE_TTL = 120 # 2 minutes — short TTL for data freshness | |
| def make_tool_cache_key(tool_name: str, args: dict) -> str: | |
| """Create a cache key from tool name + sorted args.""" | |
| args_str = json.dumps(args, sort_keys=True).lower().strip() | |
| return "tool:v1:" + hashlib.sha256(f"{tool_name}:{args_str}".encode()).hexdigest() | |
| def get_cached_tool_result(tool_name: str, args: dict) -> str | None: | |
| if r is None: | |
| return None | |
| try: | |
| key = make_tool_cache_key(tool_name, args) | |
| value = r.get(key) | |
| if value: | |
| logger.info("Tool cache hit", extra={ | |
| "event": "tool_cache_hit", "tool": tool_name | |
| }) | |
| return value | |
| return None | |
| except Exception as e: | |
| logger.warning("Tool cache get failed", extra={"event": "tool_cache_error", "error": str(e)}) | |
| return None | |
| def set_cached_tool_result(tool_name: str, args: dict, result: str) -> None: | |
| if r is None: | |
| return | |
| try: | |
| key = make_tool_cache_key(tool_name, args) | |
| r.setex(key, TOOL_CACHE_TTL, result) | |
| logger.info("Tool cache set", extra={ | |
| "event": "tool_cache_set", "tool": tool_name | |
| }) | |
| except Exception as e: | |
| logger.warning("Tool cache set failed", extra={"event": "tool_cache_error", "error": str(e)}) |