"""Generic TTL cache decorator.""" import time from functools import wraps from typing import Any, Callable, Dict import structlog logger = structlog.get_logger() def ttl_cache(seconds: int): """ Decorator that caches the return value of a function for `seconds` seconds. The cache is keyed by the function's arguments. """ def decorator(func: Callable) -> Callable: cache: Dict[Any, Dict[str, Any]] = {} @wraps(func) def wrapper(*args, **kwargs): key = (args, frozenset(kwargs.items())) now = time.time() if key in cache and now - cache[key]["time"] < seconds: logger.debug(f"Cache hit for {func.__name__}") return cache[key]["value"] result = func(*args, **kwargs) cache[key] = {"value": result, "time": now} return result return wrapper return decorator