Files
overub/core/cache.py
2025-12-21 17:12:32 +01:00

55 lines
1.5 KiB
Python

import time
from collections import OrderedDict
from dataclasses import dataclass
from typing import Any, Optional
@dataclass
class CacheItem:
value: Any
expires_at: Optional[float] = None
class Cache:
def __init__(self, max_size: int = 1000) -> None:
self.max_size = max_size
self._store: "OrderedDict[str, CacheItem]" = OrderedDict()
self._hits = 0
self._misses = 0
def get(self, key: str) -> Optional[Any]:
item = self._store.get(key)
if item is None:
self._misses += 1
return None
if item.expires_at and item.expires_at <= time.time():
self._store.pop(key, None)
self._misses += 1
return None
self._store.move_to_end(key)
self._hits += 1
return item.value
def set(self, key: str, value: Any, ttl: Optional[int] = None) -> None:
expires_at = time.time() + ttl if ttl else None
self._store[key] = CacheItem(value=value, expires_at=expires_at)
self._store.move_to_end(key)
self._evict()
def delete(self, key: str) -> None:
self._store.pop(key, None)
def clear(self) -> None:
self._store.clear()
def _evict(self) -> None:
while len(self._store) > self.max_size:
self._store.popitem(last=False)
def stats(self) -> dict[str, int]:
return {
"size": len(self._store),
"hits": self._hits,
"misses": self._misses,
}