# HG changeset patch # User Marcin Kuzminski # Date 2019-07-18 19:12:48 # Node ID 58b00196539abce216678da4c831930e604eabdd # Parent 6741e7c06989911065ec106c2d0c4c33fc4d6d2c caches: newly generated cache object should have always unique UIDs to prevent situation when after restart of services we get back to initial cache keys. diff --git a/rhodecode/lib/rc_cache/utils.py b/rhodecode/lib/rc_cache/utils.py --- a/rhodecode/lib/rc_cache/utils.py +++ b/rhodecode/lib/rc_cache/utils.py @@ -284,13 +284,22 @@ class InvalidationContext(object): self.proc_id, self.thread_id, self.cache_key) self.compute_time = 0 - def get_or_create_cache_obj(self, uid, invalidation_namespace=''): - cache_obj = CacheKey.get_active_cache(self.cache_key) + def get_or_create_cache_obj(self, cache_type, invalidation_namespace=''): + invalidation_namespace = invalidation_namespace or self.invalidation_namespace + # fetch all cache keys for this namespace and convert them to a map to find if we + # have specific cache_key object registered. We do this because we want to have + # all consistent cache_state_uid for newly registered objects + cache_obj_map = CacheKey.get_namespace_map(invalidation_namespace) + cache_obj = cache_obj_map.get(self.cache_key) log.debug('Fetched cache obj %s using %s cache key.', cache_obj, self.cache_key) - invalidation_namespace = invalidation_namespace or self.invalidation_namespace if not cache_obj: new_cache_args = invalidation_namespace - cache_obj = CacheKey(self.cache_key, cache_args=new_cache_args) + first_cache_obj = next(cache_obj_map.itervalues()) if cache_obj_map else None + cache_state_uid = None + if first_cache_obj: + cache_state_uid = first_cache_obj.cache_state_uid + cache_obj = CacheKey(self.cache_key, cache_args=new_cache_args, + cache_state_uid=cache_state_uid) return cache_obj def __enter__(self): @@ -300,7 +309,7 @@ class InvalidationContext(object): """ log.debug('Entering cache invalidation check context: %s', self.invalidation_namespace) # register or get a new key based on uid - self.cache_obj = self.get_or_create_cache_obj(uid=self.uid) + self.cache_obj = self.get_or_create_cache_obj(cache_type=self.uid) cache_data = self.cache_obj.get_dict() self._start_time = time.time() if self.cache_obj.cache_active: diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -3521,7 +3521,7 @@ class CacheKey(Base, BaseModel): self.cache_args = cache_args self.cache_active = False # first key should be same for all entries, since all workers should share it - self.cache_state_uid = cache_state_uid or self.generate_new_state_uid(based_on=cache_args) + self.cache_state_uid = cache_state_uid or self.generate_new_state_uid() def __unicode__(self): return u"<%s('%s:%s[%s]')>" % ( @@ -3598,6 +3598,12 @@ class CacheKey(Base, BaseModel): return inv_obj return None + @classmethod + def get_namespace_map(cls, namespace): + return { + x.cache_key: x + for x in cls.query().filter(cls.cache_args == namespace)} + class ChangesetComment(Base, BaseModel): __tablename__ = 'changeset_comments'