2019-09-02 13:07:26 +00:00
|
|
|
import hashlib, time, typing, uuid
|
2019-10-08 11:20:08 +00:00
|
|
|
from src import PollHook
|
2018-09-29 11:53:39 +00:00
|
|
|
|
2019-10-08 11:20:08 +00:00
|
|
|
class Cache(PollHook.PollHook):
|
2018-09-29 11:53:39 +00:00
|
|
|
def __init__(self):
|
|
|
|
self._items = {}
|
2019-09-02 13:07:26 +00:00
|
|
|
|
2019-09-20 10:47:57 +00:00
|
|
|
self._cached_expiration = None
|
|
|
|
|
2019-09-02 13:07:26 +00:00
|
|
|
def cache_key(self, key: str):
|
|
|
|
return "sha1:%s" % hashlib.sha1(key.encode("utf8")).hexdigest()
|
|
|
|
|
|
|
|
def cache(self, key: str, value: typing.Any) -> str:
|
|
|
|
return self._cache(key, value, None)
|
|
|
|
def temporary_cache(self, key: str, value: typing.Any, timeout: float
|
|
|
|
)-> str:
|
|
|
|
return self._cache(key, value, time.monotonic()+timeout)
|
|
|
|
def _cache(self, key: str, value: typing.Any,
|
|
|
|
expiration: typing.Optional[float]) -> str:
|
|
|
|
id = self.cache_key(key)
|
2019-09-20 10:47:57 +00:00
|
|
|
self._cached_expiration = None
|
2019-09-02 13:07:26 +00:00
|
|
|
self._items[id] = [key, value, expiration]
|
2018-09-29 11:53:39 +00:00
|
|
|
return id
|
|
|
|
|
2019-10-08 11:20:08 +00:00
|
|
|
def next(self) -> typing.Optional[float]:
|
2019-09-20 10:47:57 +00:00
|
|
|
if not self._cached_expiration == None:
|
|
|
|
return self._cached_expiration
|
|
|
|
|
2019-09-02 13:07:26 +00:00
|
|
|
expirations = [value[-1] for value in self._items.values()]
|
2018-09-29 11:53:39 +00:00
|
|
|
expirations = list(filter(None, expirations))
|
|
|
|
if not expirations:
|
|
|
|
return None
|
2019-06-22 22:30:15 +00:00
|
|
|
now = time.monotonic()
|
|
|
|
expirations = [e-now for e in expirations]
|
2019-09-20 10:47:57 +00:00
|
|
|
|
|
|
|
expiration = max(min(expirations), 0)
|
|
|
|
self._cached_expiration = expiration
|
|
|
|
return expiration
|
2018-09-29 11:53:39 +00:00
|
|
|
|
2019-10-08 11:20:08 +00:00
|
|
|
def call(self):
|
2018-09-29 11:53:39 +00:00
|
|
|
now = time.monotonic()
|
|
|
|
expired = []
|
2019-09-02 13:07:26 +00:00
|
|
|
for id in self._items.keys():
|
|
|
|
key, value, expiration = self._items[id]
|
2018-09-29 11:53:39 +00:00
|
|
|
if expiration and expiration <= now:
|
|
|
|
expired.append(id)
|
|
|
|
for id in expired:
|
2019-09-20 10:47:57 +00:00
|
|
|
self._cached_expiration = None
|
2018-09-29 11:53:39 +00:00
|
|
|
del self._items[id]
|
|
|
|
|
2019-09-02 13:07:26 +00:00
|
|
|
def has_item(self, key: typing.Any) -> bool:
|
|
|
|
return self.cache_key(key) in self._items
|
2018-09-29 11:53:39 +00:00
|
|
|
|
2019-09-02 13:07:26 +00:00
|
|
|
def get(self, key: str) -> typing.Any:
|
|
|
|
key, value, expiration = self._items[self.cache_key(key)]
|
|
|
|
return value
|
|
|
|
def remove(self, key: str):
|
2019-09-20 10:47:57 +00:00
|
|
|
self._cached_expiration = None
|
2019-09-02 13:07:26 +00:00
|
|
|
del self._items[self.cache_key(key)]
|
2018-09-29 11:53:39 +00:00
|
|
|
|
2019-09-02 13:07:26 +00:00
|
|
|
def get_expiration(self, key: typing.Any) -> float:
|
|
|
|
key, value, expiration = self._items[self.cache_key(key)]
|
2018-09-29 11:53:39 +00:00
|
|
|
return expiration
|
2019-09-02 13:07:26 +00:00
|
|
|
def until_expiration(self, key: typing.Any) -> float:
|
|
|
|
expiration = self.get_expiration(key)
|
2018-09-29 11:53:39 +00:00
|
|
|
return expiration-time.monotonic()
|