Last active
October 17, 2022 09:55
-
-
Save mtovmassian/9038dd0c51e103cf6f82dd25017b7632 to your computer and use it in GitHub Desktop.
Cache store with memoizing behavior and decorator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import logging | |
import pickle | |
from datetime import datetime | |
from sys import getsizeof | |
logger = logging.getLogger(__name__) | |
class CacheStore: | |
def __init__(self, maxsize, expiration_secs): | |
self.maxsize = maxsize | |
self.expiration_secs = expiration_secs | |
self.cache_store = {} | |
def memoize(self, func, *args): | |
logger.info("Memoizing call to function {function_name} with arguments {arguments}".format( | |
function_name=func.func_name, | |
arguments=args | |
) | |
) | |
cache_key = ",".join(map(str, args)) | |
cached_item = self.get_item(cache_key) | |
if cached_item and not self.is_item_expired(cached_item): | |
logger.info("Function result retrieved from cache.") | |
return cached_item["data"] | |
logger.info("Function result retrieved from compute.") | |
data = func(*args) | |
self.add_item(cache_key, data) | |
return data | |
def is_item_expired(self, item): | |
datetime_now = datetime.utcnow() | |
item_datetime = item["datetime"] | |
return (datetime_now - item_datetime).total_seconds() > self.expiration_secs | |
def is_oversized(self): | |
return getsizeof(pickle.dumps(self.cache_store)) > self.maxsize | |
def flush_all(self): | |
self.cache_store = {} | |
def get_item(self, key): | |
return self.cache_store.get(key, None) | |
def add_item(self, key, data): | |
self.__add_item(key, data) | |
if self.is_oversized(): | |
logger.info("Flushing cache store since it reached its maximal size.") | |
self.flush_all() | |
self.__add_item(key, data) | |
def __add_item(self, key, data): | |
item = { | |
"datetime": datetime.utcnow(), | |
"data": data | |
} | |
self.cache_store[key] = item | |
def cache(maxsize=1000000, expiration_secs=60): | |
def decorator(func): | |
cache_store = CacheStore(maxsize, expiration_secs) | |
def wrapper(*args): | |
return cache_store.memoize(func, *args) | |
return wrapper | |
return decorator |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment