from __future__ import annotations import asyncio import time from typing import Any class EntityCache: def __init__(self, ttl: int = 600, max_size: int = 500): self._ttl = ttl self._max_size = max_size self._cache: dict[str, tuple[Any, float]] = {} self._access_order: list[str] = [] self._lock = asyncio.Lock() def _now(self) -> float: return time.monotonic() async def get(self, key: str) -> Any | None: async with self._lock: entry = self._cache.get(key) if entry is None: return None value, ts = entry if self._now() - ts > self._ttl: self._cache.pop(key, None) if key in self._access_order: self._access_order.remove(key) return None if key in self._access_order: self._access_order.remove(key) self._access_order.append(key) return value async def set(self, key: str, value: Any) -> None: async with self._lock: if key in self._cache: self._cache[key] = (value, self._now()) if key in self._access_order: self._access_order.remove(key) self._access_order.append(key) return if len(self._cache) >= self._max_size: oldest = self._access_order.pop(0) self._cache.pop(oldest, None) self._cache[key] = (value, self._now()) self._access_order.append(key) async def delete(self, key: str) -> None: async with self._lock: self._cache.pop(key, None) if key in self._access_order: self._access_order.remove(key) async def clear(self) -> None: async with self._lock: self._cache.clear() self._access_order.clear() async def stats(self) -> dict: async with self._lock: return { "size": len(self._cache), "max_size": self._max_size, "ttl": self._ttl, }