from datetime import datetime from abc import ABCMeta, abstractmethod from six import add_metaclass from util.expiresdict import ExpiresDict from util.timedeltastring import convert_to_timedelta def is_not_none(value): return value is not None @add_metaclass(ABCMeta) class DataModelCache(object): """ Defines an interface for cache storing and returning tuple data model objects. """ @abstractmethod def retrieve(self, cache_key, loader, should_cache=is_not_none): """ Checks the cache for the specified cache key and returns the value found (if any). If none found, the loader is called to get a result and populate the cache. """ pass class NoopDataModelCache(DataModelCache): """ Implementation of the data model cache which does nothing. """ def retrieve(self, cache_key, loader, should_cache=is_not_none): return loader() class InMemoryDataModelCache(DataModelCache): """ Implementation of the data model cache backed by an in-memory dictionary. """ def __init__(self): self.cache = ExpiresDict(rebuilder=lambda: {}) def retrieve(self, cache_key, loader, should_cache=is_not_none): not_found = [None] result = self.cache.get(cache_key.key, default_value=not_found) if result != not_found: return result result = loader() if should_cache(result): expires = convert_to_timedelta(cache_key.expiration) + datetime.now() self.cache.set(cache_key.key, result, expires=expires) return result