OFS.Cache remixed by DJ Lessbugs
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Zope 2 |
Invalid
|
Wishlist
|
Unassigned |
Bug Description
I've refactored OFS/Cache.py to include a few featurettes I needed for a new CacheManager implementation and squashed a troup of bugs in the process. Here's the summary:
>Bugs squashed --
> Cacheable.
> could be called ttw
> CacheManager.
> could be called by restricted code
> CacheManager.
> under atypical conditions (Change cache settings
> permission given without View management screens
> given in kind, maybe a "lord of the cache"
> scenario? [obviously a very minor problem]) this
> method could be used to examine an object hierarchy
> which wouldn't otherwise be visible to a user
>Noteworthy improvements --
> removed all 4 bare except clauses in Cache.py
> ~100 lines less code than before
> uses declarative security model throughout
>Featurettes introduced --
> better exception interface
> support for weakref.proxy wrapped Cache instances in
> Cacheable mix-in
The case for a new exception interface:
The current Cache.py uses bare except clauses to ignore and log any exceptions raised by Cache.ZCache_
The case for support weakref ProxyTypes:
When resetting the properties of an active RAM Cache the RAM Cache Manager simply makes some adjustments and lets the cache adjust itself naturally at the given cleanup interval. That works great for the RAM Cache product, but it doesn't work great for all cache products. There are times when resetting the properties of an active cache could mean invoking expensive thread locks to do a mass cleanup of the internal data structures. (Generally this will occur anytime you change a property which then means having to examine or change every object currently in the cache.) To avoid the overhead of a long-running cache scrubing its can be entirely acceptable to just throw the cache out entirely and start over, and weakref proxy objects give us just the mechanism to do this painlessly. The refactored Cache.py allows for CacheManager.
This implies the following behavior for the 3 affected methods:
ZCacheable_get -- invalidates its volatile reference and returns default, just like a normal cache miss
ZCacheable_set -- invalidates its volatile reference, this will incur another cache miss in the future at the time of the next ZCacheable_get()
ZCacheable_
Risk factors, challenged assumptions, & API changes:
All in all the refactored code is almost totally backwards compatible, there are only a few minor API changes, in particular:
The Cache.py module variables ViewManagementS
The managersExist() function was removed from the Cache.py module, it was only called in one spot from one another def in the same module so I just inlined it. Nowhere else in the entire Zope code base was this function referenced, nor in any of the Cache products on Zope.org.
Caches which depend on the greedy except nature of the old API will not behave as expected. I'd argue they were buggy anyway, but they can easily use the new CacheException base class to fix the issue. I'll include patches which do just this for RAMCacheManager.py. I examined the Cache products on Zope.org and found no behavior which relied upon the greedy nature of the old API.
There is some rather bizzare behavior which occurs when you've got nested cache managers, particularly of the same name. AFAICT this behavior was intentional, so I didn't change it, but if you add a cache manager with the same id as a manager above it in the containment hierarchy, documents which used to be assocated with the higher manager will be automatically placed into the new manager instead. Same story for deletion.
Appendix:
Cache products found on zope.org which I reference above were FSCacheManager and ZopeProxyCacheM
Changed in zope2: | |
importance: | Medium → Wishlist |
Changed in zope2: | |
status: | New → Triaged |
Uploaded: cachemanagers.diff
and here's a patch which accompanies the refactor, used to fit the current StandardCacheMa nagers to the refactored Cache.py exception API, use the base class's notion of permission values rather than hardcode them, and lastly remove all 3 bare except clauses from RAMCacheManager.py