Edgewall Software

TracDev/Proposals/CacheInvalidation: cache-manager-automatic-key.patch

File cache-manager-automatic-key.patch, 5.2 KB (added by cboos, 3 years ago)

applies on top of attachment:cache-manager_get-corner-cases.patch

  • trac/cache.py

    CacheValidation: simplify the setup of a cached value
     - added documentation for the decorators
     - infers the cache key from the retrieval method's module and name
    
    diff --git a/trac/cache.py b/trac/cache.py
    a b  
    2525__all__ = ["CacheManager", "cached", "cached_value"] 
    2626 
    2727 
     28def cached_value(meth): 
     29    """Method decorator creating a cached attribute from a data retrieval 
     30    method. 
     31 
     32    Accessing the cached attribute gives back the cached value. The data 
     33    retrieval method will be called as needed by the CacheManager. 
     34    Invalidating the cache for this value is done by `del`eting the attribute. 
     35     
     36    Note that the cache validity is maintained using a table in the database. 
     37    Most notably, a cache invalidation will trigger a commit, so don't do this 
     38    while another database operation is in progress. 
     39 
     40    If more control over the transaction is needed, see the `cached` decorator. 
     41    """ 
     42    return CachedValue(meth.__module__ + '.' + meth.__name__, meth) 
     43 
     44def cached(meth): 
     45    """Method decorator creating a cached attribute from a data retrieval 
     46    method. 
     47 
     48    In contrast with cached attributes created by the `cached_value` decorator, 
     49    accessing a cached attribute created with `cached` will not directly give  
     50    back the cached value.  Instead, this will return a proxy object with `get` 
     51    and `invalidate` methods, both accepting a `db` connection. 
     52    After calling `invalidate(db)`, doing a `commit` is the responsibility  
     53    of the caller. 
     54    """ 
     55    return Cached(meth.__module__ + '.' + meth.__name__, meth) 
     56 
     57 
    2858class CachedValue(object): 
    2959    """Descriptor for a cached attribute value.""" 
    3060    def __init__(self, key, retriever): 
     
    3666        if instance is None: 
    3767            return self 
    3868        return CacheManager(instance.env).get( 
    39             self.key, partial(self.retriever, instance)) 
     69                self.key, partial(self.retriever, instance)) 
    4070         
    4171    def __delete__(self, instance): 
    4272        CacheManager(instance.env).invalidate(self.key) 
    4373 
    44  
    45 def cached_value(key): 
    46     """Method decorator creating a cached attribute value from a data 
    47     retrieval method. 
    48      
    49     This decorator should be used when data retrieval and cache 
    50     invalidation can be done in a separate transaction. 
    51     """ 
    52     def thunk(retriever): 
    53         return CachedValue(key, retriever) 
    54     return thunk 
    55  
     74class Cached(CachedValue): 
     75    """Descriptor for a cached attribute value with transaction control.""" 
     76    def __get__(self, instance, owner): 
     77        if instance is None: 
     78            return self 
     79        return CacheProxy(self.key, partial(self.retriever, instance),  
     80                          instance.env) 
    5681 
    5782class CacheProxy(object): 
    5883    """Cached attribute proxy.""" 
     
    7095        CacheManager(self.env).invalidate(self.key, db) 
    7196 
    7297 
    73 class Cached(CachedValue): 
    74     """Descriptor for a cached attribute.""" 
    75     __slots__ = [] 
    76      
    77     def __get__(self, instance, owner): 
    78         if instance is None: 
    79             return self 
    80         return CacheProxy(self.key, partial(self.retriever, instance), 
    81                           instance.env) 
    82  
    83  
    84 def cached(key): 
    85     """Method decorator creating a cached attribute from a data retrieval 
    86     method. 
    87      
    88     This decorator can be used when data retrieval and cache invalidation 
    89     must be done in a given transaction. 
    90     """ 
    91     def thunk(retriever): 
    92         return Cached(key, retriever) 
    93     return thunk 
    94  
    95  
    9698class CacheManager(Component): 
    9799    """Cache manager component.""" 
    98100     
  • trac/ticket/api.py

    diff --git a/trac/ticket/api.py b/trac/ticket/api.py
    a b  
    191191        """Invalidate ticket field cache.""" 
    192192        self.fields.invalidate(db) 
    193193 
    194     @cached('ticket.TicketSystem.fields') 
     194    @cached 
    195195    def fields(self, db): 
    196196        """Return the list of fields available for tickets.""" 
    197197        from trac.ticket import model 
     
    273273    def get_custom_fields(self): 
    274274        return [f.copy() for f in self.custom_fields] 
    275275 
    276     @cached_value('ticket.TicketSystem.custom_fields') 
     276    @cached_value 
    277277    def custom_fields(self, db): 
    278278        """Return the list of custom ticket fields available for tickets.""" 
    279279        fields = [] 
  • trac/wiki/api.py

    diff --git a/trac/wiki/api.py b/trac/wiki/api.py
    a b  
    176176        For public sites where anonymous users can edit the wiki it is 
    177177        recommended to leave this option disabled (which is the default).""") 
    178178 
    179     @cached_value('wiki.WikiSystem.pages') 
     179    @cached_value 
    180180    def pages(self, db): 
    181181        """Return the names of all existing wiki pages.""" 
    182182        cursor = db.cursor() 
  • trac/wiki/interwiki.py

    diff --git a/trac/wiki/interwiki.py b/trac/wiki/interwiki.py
    a b  
    9696        if page.name == InterWikiMap._page_name: 
    9797            del self.interwiki_map 
    9898 
    99     @cached_value('wiki.interwiki.map') 
     99    @cached_value 
    100100    def interwiki_map(self, db): 
    101101        """Map from upper-cased namespaces to (namespace, prefix, title)  
    102102        values.