forked from retoor/devplacepy
update
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
# retoor <retoor@molodetz.nl>
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
class TTLCache:
|
||||
def __init__(self, ttl: int, max_size: int = 0):
|
||||
self.ttl = ttl
|
||||
self.max_size = max_size
|
||||
self._store: OrderedDict[str, tuple[object, float]] = OrderedDict()
|
||||
|
||||
def get(self, key: str):
|
||||
entry = self._store.get(key)
|
||||
if entry is None:
|
||||
return None
|
||||
value, expiry = entry
|
||||
if time.time() >= expiry:
|
||||
self._store.pop(key, None)
|
||||
return None
|
||||
self._store.move_to_end(key)
|
||||
return value
|
||||
|
||||
def set(self, key: str, value) -> None:
|
||||
self._store[key] = (value, time.time() + self.ttl)
|
||||
self._store.move_to_end(key)
|
||||
if self.max_size and len(self._store) > self.max_size:
|
||||
self._store.popitem(last=False)
|
||||
|
||||
def pop(self, key: str) -> None:
|
||||
self._store.pop(key, None)
|
||||
|
||||
def clear(self) -> None:
|
||||
self._store.clear()
|
||||
|
||||
|
||||
class CacheStateGate:
|
||||
def __init__(self, *, ttl: int = 60, max_staleness: float = 5.0):
|
||||
self.ttl = ttl
|
||||
self.max_staleness = max_staleness
|
||||
self._cache = TTLCache(ttl=ttl)
|
||||
self._versions: dict[str, int] = {}
|
||||
self._bumped_at: dict[str, float] = {}
|
||||
|
||||
def get_version(self, name: str) -> int:
|
||||
return int(self._versions.get(name, 0))
|
||||
|
||||
def bump(self, name: str) -> int:
|
||||
next_version = self.get_version(name) + 1
|
||||
self._versions[name] = next_version
|
||||
self._bumped_at[name] = time.time()
|
||||
self._cache.clear()
|
||||
return next_version
|
||||
|
||||
def get(self, key: str, version_name: str, loader):
|
||||
bumped_at = self._bumped_at.get(version_name, 0.0)
|
||||
if bumped_at and (time.time() - bumped_at) < self.max_staleness:
|
||||
self._cache.pop(key)
|
||||
version_key = f"{version_name}:{self.get_version(version_name)}"
|
||||
cached = self._cache.get(version_key)
|
||||
if cached is not None:
|
||||
return cached
|
||||
value = loader()
|
||||
self._cache.set(version_key, value)
|
||||
return value
|
||||
Reference in New Issue
Block a user