I just had my socks knocked off by Rails'' caching system. However there was one thing that I tried but was unable to do: Essentially, I want to be able to expire entire sets of cached fragments at one time, without knowing all the cache keys of the individual elements inside. In my application, there is a portion of each user''s profile screen that is cached, the content of which depends on data from various objects in the system. If any one of those objects is updated, I want to wipe out all of the cached user profile fragments. Currently, the only way I can do this is to get a list of users and loop through them, wiping out the cached fragment of each. Ideally I would be able to just wipe out the entire user profile cache set with one call to expire. Does this sound like a reasonable thing to want to do? It seems like the current convention for cache keys (controller/action/id) lends itself to a nice solution: if I expire the cache for "mycontroller/myaction", why not also automatically expire the cache for any cache keys of the form "mycontroller/myaction/myid"? Likewise, if I expire "mycontroller", then "mycontroller/myaction" and "mycontroller/myaction/myid" get expired, too. Is there a case where you would not want this to happen? Michael PS -- I''m all about working on a patch for this if the community thinks it''s a good idea.
+1 On Wed, 23 Feb 2005 01:16:33 -0600, Michael Lovitt <lovitt-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I just had my socks knocked off by Rails'' caching system. However > there was one thing that I tried but was unable to do: > > Essentially, I want to be able to expire entire sets of cached > fragments at one time, without knowing all the cache keys of the > individual elements inside. In my application, there is a portion of > each user''s profile screen that is cached, the content of which > depends on data from various objects in the system. If any one of > those objects is updated, I want to wipe out all of the cached user > profile fragments. Currently, the only way I can do this is to get a > list of users and loop through them, wiping out the cached fragment of > each. Ideally I would be able to just wipe out the entire user profile > cache set with one call to expire. > > Does this sound like a reasonable thing to want to do? It seems like > the current convention for cache keys (controller/action/id) lends > itself to a nice solution: if I expire the cache for > "mycontroller/myaction", why not also automatically expire the cache > for any cache keys of the form "mycontroller/myaction/myid"? Likewise, > if I expire "mycontroller", then "mycontroller/myaction" and > "mycontroller/myaction/myid" get expired, too. Is there a case where > you would not want this to happen? > > Michael > > PS -- I''m all about working on a patch for this if the community > thinks it''s a good idea. > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- --Scott
Michael Lovitt wrote:>I just had my socks knocked off by Rails'' caching system. However >there was one thing that I tried but was unable to do: > >Essentially, I want to be able to expire entire sets of cached >fragments at one time, without knowing all the cache keys of the >individual elements inside. In my application, there is a portion of >each user''s profile screen that is cached, the content of which >depends on data from various objects in the system. If any one of >those objects is updated, I want to wipe out all of the cached user >profile fragments. Currently, the only way I can do this is to get a >list of users and loop through them, wiping out the cached fragment of >each. Ideally I would be able to just wipe out the entire user profile >cache set with one call to expire. > >Does this sound like a reasonable thing to want to do? It seems like >the current convention for cache keys (controller/action/id) lends >itself to a nice solution: if I expire the cache for >"mycontroller/myaction", why not also automatically expire the cache >for any cache keys of the form "mycontroller/myaction/myid"? Likewise, >if I expire "mycontroller", then "mycontroller/myaction" and >"mycontroller/myaction/myid" get expired, too. Is there a case where >you would not want this to happen? > >I have already implemented something similar, here is what I did: I added a method expire_matched_fragments to Module Fragments: (caching.rb) def expire_matched_fragments(re=Regexp.new(''/*/''), options = {}) fragment_cache_store.delete_matched(re, options) logger.info "Expired all fragments matching: #{re} " unless logger.nil? end and a method delete_matched to class Memorystore def delete_matched(re, options = {}) #:nodoc: @mutex.synchronize { @data.delete_if {|k,v| k =~ re} } end This makes it available to MemoryStore, DRbStore and MemCacheStore. A similar method needs to be added to FileStore, which I haven''t done yet, since I''m not using it. All that remains to be done is calling expire_matched_fragments with the appropriate regular expression from a filter class, as described in the rails docs for regular action caching. -- stefan
> I have already implemented something similar, here is what I did: > > I added a method expire_matched_fragments to Module Fragments: (caching.rb) > > def expire_matched_fragments(re=Regexp.new(''/*/''), options = {}) > fragment_cache_store.delete_matched(re, options) > logger.info "Expired all fragments matching: #{re} " unless > logger.nil? > end > > and a method delete_matched to class Memorystore > > def delete_matched(re, options = {}) #:nodoc: > @mutex.synchronize { @data.delete_if {|k,v| k =~ re} } > end > > This makes it available to MemoryStore, DRbStore and MemCacheStore. A > similar method needs to be added to FileStore, which I haven''t done yet, > since I''m not using it. > > All that remains to be done is calling expire_matched_fragments with the > appropriate regular expression from a filter class, as described in the > rails docs for regular action caching.I added support for expire_matched_fragments in the FileStore. It''s kind of messy, so maybe someone can write some more elegant code. Also, it won''t delete caches from other sites. It''s been submitted as a patch: http://dev.rubyonrails.com/ticket/927 -- rick http://techno-weenie.net