import json import os import time import uuid from typing import Any from config.default import CACHE_DIR # overridden by app config after import def _cache_path(key: str) -> str: safe_key = key.replace("/", "_").replace(" ", "_") return os.path.join(CACHE_DIR, f"{safe_key}.json") def get_cached(key: str, ttl: int | None = None) -> Any: """Return cached data, or None if missing or older than ttl seconds.""" path = _cache_path(key) try: if not os.path.exists(path): return None if ttl is not None and time.time() - os.path.getmtime(path) > ttl: return None with open(path) as f: return json.load(f) except (OSError, json.JSONDecodeError): return None def set_cached(key: str, data: Any) -> None: os.makedirs(CACHE_DIR, exist_ok=True) path = _cache_path(key) tmp_path = f"{path}.{os.getpid()}.{uuid.uuid4().hex}.tmp" with open(tmp_path, "w") as f: json.dump(data, f, indent=2) os.replace(tmp_path, path)