fly-trader / fly_trader /ui /cache.py
bryceweiner's picture
release 2 (2c43cfc9d2) (part 2)
67cab91 verified
Raw History Blame Contribute Delete
1.34 kB
"""A small thread-safe TTL cache for the console's slow reads (parquet globs, chain balances, the brain's files)."""
from __future__ import annotations
import functools
import threading
import time
from collections import OrderedDict
def ttl_cache(ttl: float | None = None, maxsize: int = 128):
"""Memoize by positional and keyword arguments for ``ttl`` seconds (None: forever, like a resource). Concurrent misses
on one key may compute twice; the last result wins."""
def deco(fn):
store: OrderedDict = OrderedDict(); lock = threading.Lock()
@functools.wraps(fn)
def wrapper(*args, **kwargs):
key = (args, tuple(sorted(kwargs.items())))
now = time.monotonic()
with lock:
hit = store.get(key)
if hit is not None and (ttl is None or now - hit[0] < ttl):
store.move_to_end(key)
return hit[1]
val = fn(*args, **kwargs)
with lock:
store[key] = (now, val); store.move_to_end(key)
while len(store) > maxsize:
store.popitem(last=False)
return val
def cache_clear():
with lock:
store.clear()
wrapper.cache_clear = cache_clear
return wrapper
return deco