diff options
Diffstat (limited to 'src/pybind/mgr/dashboard/plugins/ttl_cache.py')
-rw-r--r-- | src/pybind/mgr/dashboard/plugins/ttl_cache.py | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/src/pybind/mgr/dashboard/plugins/ttl_cache.py b/src/pybind/mgr/dashboard/plugins/ttl_cache.py new file mode 100644 index 000000000..b316151e7 --- /dev/null +++ b/src/pybind/mgr/dashboard/plugins/ttl_cache.py @@ -0,0 +1,57 @@ +""" +This is a minimal implementation of TTL-ed lru_cache function. + +Based on Python 3 functools and backports.functools_lru_cache. +""" +from __future__ import absolute_import + +from collections import OrderedDict +from functools import wraps +from threading import RLock +from time import time + +try: + from typing import Tuple +except ImportError: + pass # For typing only + + +def ttl_cache(ttl, maxsize=128, typed=False): + if typed is not False: + raise NotImplementedError("typed caching not supported") + + def decorating_function(function): + cache = OrderedDict() # type: OrderedDict[object, Tuple[bool, float]] + stats = [0, 0, 0] + rlock = RLock() + setattr(function, 'cache_info', lambda: + "hits={}, misses={}, expired={}, maxsize={}, currsize={}".format( + stats[0], stats[1], stats[2], maxsize, len(cache))) + + @wraps(function) + def wrapper(*args, **kwargs): + key = args + tuple(kwargs.items()) + with rlock: + refresh = True + if key in cache: + (ret, ts) = cache[key] + del cache[key] + if time() - ts < ttl: + refresh = False + stats[0] += 1 + else: + stats[2] += 1 + + if refresh: + ret = function(*args, **kwargs) + ts = time() + if len(cache) == maxsize: + cache.popitem(last=False) + stats[1] += 1 + + cache[key] = (ret, ts) + + return ret + + return wrapper + return decorating_function |