Added age as criteria to not use the cached value added

This commit is contained in:
Dirk Alders 2024-09-15 13:24:04 +02:00
parent 3b32ca5e20
commit 12c526046f

View File

@ -24,13 +24,12 @@ caching (Caching Module)
""" """
__DEPENDENCIES__ = [] __DEPENDENCIES__ = []
import hashlib
import hmac
import json import json
import logging import logging
import os import os
import pickle import pickle
import sys import sys
import time
try: try:
from config import APP_NAME as ROOT_LOGGER_NAME from config import APP_NAME as ROOT_LOGGER_NAME
@ -81,13 +80,20 @@ class property_cache_pickle(object):
""" """
LOG_PREFIX = 'PickCache:' LOG_PREFIX = 'PickCache:'
DATA_VERSION_TAG = '_property_cache_data_version_' DATA_VERSION_TAG = '_property_cache_data_version_'
STORAGE_VERSION_TAG = '_storage_version_'
UID_TAG = '_property_cache_uid_' UID_TAG = '_property_cache_uid_'
DATA_TAG = '_data_'
AGE_TAG = '_age_'
#
STORAGE_VERSION = 1
def __init__(self, source_instance, cache_filename, load_all_on_init=False, callback_on_data_storage=None): def __init__(self, source_instance, cache_filename, load_all_on_init=False, callback_on_data_storage=None, max_age=None, store_none_value=False):
self._source_instance = source_instance self._source_instance = source_instance
self._cache_filename = cache_filename self._cache_filename = cache_filename
self._load_all_on_init = load_all_on_init self._load_all_on_init = load_all_on_init
self._callback_on_data_storage = callback_on_data_storage self._callback_on_data_storage = callback_on_data_storage
self._max_age = max_age
self._store_none_value = store_none_value
self._cached_props = None self._cached_props = None
def get(self, key, default=None): def get(self, key, default=None):
@ -101,14 +107,27 @@ class property_cache_pickle(object):
if key in self.keys(): if key in self.keys():
if self._cached_props is None: if self._cached_props is None:
self._init_cache() self._init_cache()
if self._key_filter(key) not in self._cached_props: if self._max_age is None:
cache_old = False
else:
cache_old = time.time() - self._cached_props[self.AGE_TAG].get(self._key_filter(key), 0) > self._max_age
if cache_old:
logger.debug("The cached value is old, cached value will be ignored")
if self._key_filter(key) not in self._cached_props[self.DATA_TAG] or cache_old:
val = self._source_instance.get(key, None) val = self._source_instance.get(key, None)
logger.debug("%s Loading property for '%s' from source instance (%s)", self.LOG_PREFIX, key, repr(val)) logger.debug("%s Loading property for '%s' from source instance (%s)", self.LOG_PREFIX, key, repr(val))
self._cached_props[self._key_filter(key)] = val if val or self._store_none_value:
tm = int(time.time())
logger.debug("Storing value=%s with timestamp=%d to chache", val, tm)
self._cached_props[self.DATA_TAG][self._key_filter(key)] = val
self._cached_props[self.AGE_TAG][self._key_filter(key)] = tm
self._save_cache() self._save_cache()
else: else:
logger.debug("%s Providing property for '%s' from cache (%s)", self.LOG_PREFIX, key, repr(self._cached_props.get(self._key_filter(key), default))) return val
return self._cached_props.get(self._key_filter(key), default) else:
logger.debug("%s Providing property for '%s' from cache (%s)", self.LOG_PREFIX,
key, repr(self._cached_props[self.DATA_TAG].get(self._key_filter(key), default)))
return self._cached_props[self.DATA_TAG].get(self._key_filter(key), default)
else: else:
logger.info("%s Key '%s' is not in cached_keys. Uncached data will be returned.", self.LOG_PREFIX, key) logger.info("%s Key '%s' is not in cached_keys. Uncached data will be returned.", self.LOG_PREFIX, key)
return self._source_instance.get(key, default) return self._source_instance.get(key, default)
@ -125,17 +144,31 @@ class property_cache_pickle(object):
else: else:
return self._cached_props.get(self.DATA_VERSION_TAG, None) return self._cached_props.get(self.DATA_VERSION_TAG, None)
def _storage_version(self):
if self._cached_props is None:
return None
else:
return self._cached_props.get(self.STORAGE_VERSION_TAG, None)
def _init_cache(self): def _init_cache(self):
if not self._load_cache() or self._source_instance.uid() != self._uid() or self._source_instance.data_version() > self._data_version(): load_cache = self._load_cache()
if self._uid() is not None and self._source_instance.uid() != self._uid(): uid = self._source_instance.uid() != self._uid()
data_version = self._source_instance.data_version() > self._data_version()
storage_version = self._storage_version() != self.STORAGE_VERSION
#
if not load_cache or uid or data_version or storage_version:
if self._uid() is not None and uid:
logger.debug("%s Source uid changed, ignoring previous cache data", self.LOG_PREFIX) logger.debug("%s Source uid changed, ignoring previous cache data", self.LOG_PREFIX)
if self._data_version() is not None and self._source_instance.data_version() > self._data_version(): if self._data_version() is not None and data_version:
logger.debug("%s Data version increased, ignoring previous cache data", self.LOG_PREFIX) logger.debug("%s Data version increased, ignoring previous cache data", self.LOG_PREFIX)
self._cached_props = dict() if storage_version:
logger.debug("%s Storage version changed, ignoring previous cache data", self.LOG_PREFIX)
self._cached_props = {self.AGE_TAG: {}, self.DATA_TAG: {}}
if self._load_all_on_init: if self._load_all_on_init:
self._load_source() self._load_source()
self._cached_props[self.UID_TAG] = self._source_instance.uid() self._cached_props[self.UID_TAG] = self._source_instance.uid()
self._cached_props[self.DATA_VERSION_TAG] = self._source_instance.data_version() self._cached_props[self.DATA_VERSION_TAG] = self._source_instance.data_version()
self._cached_props[self.STORAGE_VERSION_TAG] = self.STORAGE_VERSION
self._save_cache() self._save_cache()
def _load_cache(self): def _load_cache(self):
@ -149,13 +182,6 @@ class property_cache_pickle(object):
return False return False
def _key_filter(self, key): def _key_filter(self, key):
if sys.version_info >= (3, 0):
tps = [str]
else:
tps = [str, unicode]
if type(key) in tps:
if key.endswith(self.DATA_VERSION_TAG) or key.endswith(self.UID_TAG):
return '_' + key
return key return key
def _load_source(self): def _load_source(self):