Edgewall Software

TracDev/Proposals/CacheInvalidation: cache-manager_get-corner-cases.patch

File cache-manager_get-corner-cases.patch, 1.7 KB (added by cboos, 3 years ago)

applies on top of attachment:cache-manager-r7941.patch

  • trac/cache.py

    CacheInvalidation: fixes for corner cases
     - call the `retriever` function at most once per component when a new generation is reached, not once for every out-of-date thread
     - call the `retriever` function after the new generation value is retrieved. In case there's a race, at least the next `get` will be able to call the `retriever` function again
    
    diff --git a/trac/cache.py b/trac/cache.py
    a b  
    131131            self._local.cache = local_cache = self._cache.copy() 
    132132         
    133133        db_generation = local_meta.get(key, -1) 
     134        generation = -1 
    134135         
    135136        # Try the thread-local copy first 
    136137        try: 
     
    150151            except KeyError: 
    151152                pass 
    152153             
    153             # Retrieve data from the database 
     154            if generation > db_generation:  
     155                # component's cache is newer than per-thread cache 
     156                local_meta[key] = generation 
     157                return data 
     158 
     159            # Retrieve data using the retriever callback 
    154160            self.log.debug("***** Retrieving data for '%s'", key) 
     161            # retrieve current generation 
    155162            if db is None: 
    156163                db = self.env.get_db_cnx() 
    157             data = retriever(db) 
    158164            cursor = db.cursor() 
    159165            cursor.execute("SELECT generation FROM cache WHERE key=%s", (key,)) 
    160166            row = cursor.fetchone() 
    161167            generation = row and row[0] or -1 
     168            # retrieve data for at least this generation 
     169            data = retriever(db) 
    162170            local_cache[key] = self._cache[key] = (data, generation) 
    163171            local_meta[key] = generation 
    164172            return data