41 lines
1.1 KiB
Python
41 lines
1.1 KiB
Python
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import logging
|
||
|
|
import time
|
||
|
|
from collections import OrderedDict
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
DEFAULT_TTL_SECONDS = 120
|
||
|
|
|
||
|
|
|
||
|
|
class FileCacheEntry:
|
||
|
|
__slots__ = ("file_path", "cached_at")
|
||
|
|
|
||
|
|
def __init__(self, file_path: str):
|
||
|
|
self.file_path = file_path
|
||
|
|
self.cached_at = time.monotonic()
|
||
|
|
|
||
|
|
|
||
|
|
class FileCache:
|
||
|
|
def __init__(self, ttl_seconds: int = DEFAULT_TTL_SECONDS):
|
||
|
|
self._ttl = ttl_seconds
|
||
|
|
self._entries: OrderedDict[str, FileCacheEntry] = OrderedDict()
|
||
|
|
|
||
|
|
def add(self, session_key: str, file_path: str) -> None:
|
||
|
|
self._evict_expired()
|
||
|
|
self._entries[session_key] = FileCacheEntry(file_path)
|
||
|
|
|
||
|
|
def get(self, session_key: str) -> FileCacheEntry | None:
|
||
|
|
self._evict_expired()
|
||
|
|
return self._entries.get(session_key)
|
||
|
|
|
||
|
|
def clear(self, session_key: str) -> None:
|
||
|
|
self._entries.pop(session_key, None)
|
||
|
|
|
||
|
|
def _evict_expired(self) -> None:
|
||
|
|
now = time.monotonic()
|
||
|
|
expired = [k for k, v in self._entries.items() if now - v.cached_at > self._ttl]
|
||
|
|
for k in expired:
|
||
|
|
self._entries.pop(k, None)
|