Will be used to cache blobs, thus removing the need to hit the database in most blob requests
48 lines
1.5 KiB
Python
48 lines
1.5 KiB
Python
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
|