Source code for edri.utility.cache

from collections import defaultdict
from datetime import datetime, timedelta
from pytz import timezone

__all__ = ["Cache"]


[docs] class Cache: timezone = timezone("Europe/Prague") def __init__(self) -> None: self.last_modified: defaultdict[str, datetime] = defaultdict(lambda: datetime.now(tz=self.timezone)) def __len__(self) -> int: return len(self.last_modified)
[docs] def last_change(self, key: str) -> datetime: return self.last_modified[key]
[docs] def tag(self, key: str) -> str: # Microsecond resolution: a plain integer-seconds tag would collide for # two changes in the same second, letting a stale 304 slip through. # renew() guarantees last_change() is strictly increasing per microsecond. dt = self.last_change(key) return f"{key}-{int(dt.timestamp())}{dt.microsecond:06d}"
[docs] def seed(self, key: str, when: datetime) -> None: """Set the last-change timestamp for ``key`` explicitly. Use from ``Manager.after_start()`` to pre-seed a cache key so its first ETag reflects a known baseline instead of process start time. A naive ``when`` is assumed to be in the cache timezone, keeping it comparable with the aware timestamps ``renew()`` produces. """ if when.tzinfo is None: when = when.replace(tzinfo=self.timezone) self.last_modified[key] = when
[docs] def renew(self, key: str) -> None: now = datetime.now(tz=self.timezone) previous = self.last_modified.get(key) # datetime.now() has finite resolution: two renews close enough in # time (e.g. under CPU contention) can land on the same instant, # which would break callers relying on last_change() strictly # increasing across renewals. if previous is not None and now <= previous: now = previous + timedelta(microseconds=1) self.last_modified[key] = now