[ Pobierz całość w formacie PDF ]
.[Æ2]17.1.5 Expiration of Cached ContentWhenever you use caching, you need to consider any and all situations that will cause the cache to becomestale, out of date.Then you need to write code that sweeps away the old content, so to speak, making roomfor new content to be cached in its place.Caching and Performance 43417.1.5.1 Expiring Pages and ActionsTheexpire_pageandexpire_actionmethods let you explicitly delete content from the cache, so that it isregenerated on the next request.There are various ways to identify the content to expire, but one of themis by passing a hash withurl_forconventions used elsewhere in Rails.Listing [lst:17-5] shows how we veadded expiration to thecreatemethod of the entries controller.1 def create2 @entry = @user.entries.build(params[:entry])3 if @entry.save4 expire_page :action => 'public'5 redirect_to entries_path(@entry)6 else7 render :action => 'new'8 end9 endNotice how line 4 of Listing [lst:17-5] explicitly expires the page associated with the public action.If you thinkabout it, though, it s not only thecreateaction that invalidates the cache.Theupdateanddestroyactionswould invalidate it too.In your applications, particularly when you re doing RESTful resources, remember that different representa-tions of the same resource are treated like separate requests and cached separately.If you ve cached the XMLresponse of an action, you ll have to expire it by appending:format => :xmlto the action specification.17.1.5.2 Expiring FragmentsThe sample app we ve been considering also has cached fragments to clear out, using theexpire_fragmentmethod.Now thecreateaction looks like:1 def create2 @entry = @user.entries.build(params[:entry])3 if @entry.save4 expire_page :action => 'public'5 expire_fragment(:fragment => 'entries')6 expire_fragment(:fragment => (@user.name + "_stats"))7 redirect_to entries_path(@entry)8 else9 render :action => 'new'10 end11 endThere s actually a serious problem with the expiration routine that we wrote in Listing [lst:17-6].Rememberwe said that the fragment caching of entries would work with pagination and that we d have cached fragmentskeyed like'/entries/index?page=2&fragment=entries'Caching and Performance 435As a result, just doingexpire_fragment(:fragment => 'entries')will only clear the first page from thecache.For that reason, theexpire_fragmentmethod understands regular expressions, and we ll need to usethem in our code:1 expire_fragment(%r{entries/.*})There has to be a better way to handle invalidation than remembering to stick a bunch of complicatedexpiration statements in all your action methods.Also, since caching is a unique concern, it feels likesomething that should be applied in an aspect-oriented fashion instead of procedurally.17.1.6 Automatic Cache Expiry with SweepersASweeperclass is kind of like anActiveRecordObserverobject, except that it s specialized for use in expiringcached content.When you write a sweeper, you tell it which of your models to observe for changes, just asyou would with callback classes and observers.Listing [lst:17-7] is a sweeper to keep the caching of our sample app s entries in order.1 class EntrySweeper 'entries', :action => 'public'6 expire_fragment(%r{entries/.*})7 expire_fragment(:fragment => (entry.user.name + "_stats"))8 end910 alias_method :after_save, :expire_cached_content11 alias_method :after_destroy, :expire_cached_content1213 endOnce you have aSweeperclass (put it in yourapp/modelsdirectory), you need to tell your controller to usethat sweeper in conjunction with its actions.Here s the top of the revised entries controller:1 class EntriesController [:index]4 caches_page :public5 cache_sweeper :entry_sweeper, :only => [:create, :update, :destroy]67.Caching and Performance 436Like many other controller macros, thecache_sweepermethod takes:onlyand:exceptoptions.There s noneed to bother the sweeper for actions that can t modify the state of the application, so we do indeed includethe:onlyoption in our example.Like the relatedobservers,sweepersare not limited to observing just one model.The main thing to rememberif we go down that route is that our callback methods will need to know how to handle all of them.Ruby scasestatement may come in handy, as shown in Listing [lst:17-8], a full revision of theEntrySweeper, whichmay now observeCommentas well asEntryobjects.1 class EntrySweeper 'entries', :action => 'public'6 expire_fragment(r%{entries/.*})78 user = case entry9 when Entry then record.user10 when Comment then record.entry.user11 end1213 expire_fragment(:fragment => (user.name + "_stats"))14 end1516 alias_method :after_save, :expire_cached_content17 alias_method :after_destroy, :expire_cached_content1819 endThe big gotcha with regular expression andexpire_fragmentis that it is not supported with the most commoncaching service used on Rails production systems: Memcached.17.1.7 Cache LoggingIf you ve turned on caching during development, you can actually monitor the Rails log for messages aboutcaching and expiration.1 Processing Entries#index (for 127.1 at 2007-07-20 23:07:09) [GET]2.3 Cached page: /entries.html (0.03949)45 Processing Entries#create (for 127.1 at 2007-07-20 23:10:50) [POST]6.7 Expired page: /entries.html (0.00085)It s a good way to see whether your caching is actually working as expected.Caching and Performance 43717.1 [ Pobierz caÅ‚ość w formacie PDF ]
zanotowane.pl doc.pisz.pl pdf.pisz.pl odbijak.htw.pl
.[Æ2]17.1.5 Expiration of Cached ContentWhenever you use caching, you need to consider any and all situations that will cause the cache to becomestale, out of date.Then you need to write code that sweeps away the old content, so to speak, making roomfor new content to be cached in its place.Caching and Performance 43417.1.5.1 Expiring Pages and ActionsTheexpire_pageandexpire_actionmethods let you explicitly delete content from the cache, so that it isregenerated on the next request.There are various ways to identify the content to expire, but one of themis by passing a hash withurl_forconventions used elsewhere in Rails.Listing [lst:17-5] shows how we veadded expiration to thecreatemethod of the entries controller.1 def create2 @entry = @user.entries.build(params[:entry])3 if @entry.save4 expire_page :action => 'public'5 redirect_to entries_path(@entry)6 else7 render :action => 'new'8 end9 endNotice how line 4 of Listing [lst:17-5] explicitly expires the page associated with the public action.If you thinkabout it, though, it s not only thecreateaction that invalidates the cache.Theupdateanddestroyactionswould invalidate it too.In your applications, particularly when you re doing RESTful resources, remember that different representa-tions of the same resource are treated like separate requests and cached separately.If you ve cached the XMLresponse of an action, you ll have to expire it by appending:format => :xmlto the action specification.17.1.5.2 Expiring FragmentsThe sample app we ve been considering also has cached fragments to clear out, using theexpire_fragmentmethod.Now thecreateaction looks like:1 def create2 @entry = @user.entries.build(params[:entry])3 if @entry.save4 expire_page :action => 'public'5 expire_fragment(:fragment => 'entries')6 expire_fragment(:fragment => (@user.name + "_stats"))7 redirect_to entries_path(@entry)8 else9 render :action => 'new'10 end11 endThere s actually a serious problem with the expiration routine that we wrote in Listing [lst:17-6].Rememberwe said that the fragment caching of entries would work with pagination and that we d have cached fragmentskeyed like'/entries/index?page=2&fragment=entries'Caching and Performance 435As a result, just doingexpire_fragment(:fragment => 'entries')will only clear the first page from thecache.For that reason, theexpire_fragmentmethod understands regular expressions, and we ll need to usethem in our code:1 expire_fragment(%r{entries/.*})There has to be a better way to handle invalidation than remembering to stick a bunch of complicatedexpiration statements in all your action methods.Also, since caching is a unique concern, it feels likesomething that should be applied in an aspect-oriented fashion instead of procedurally.17.1.6 Automatic Cache Expiry with SweepersASweeperclass is kind of like anActiveRecordObserverobject, except that it s specialized for use in expiringcached content.When you write a sweeper, you tell it which of your models to observe for changes, just asyou would with callback classes and observers.Listing [lst:17-7] is a sweeper to keep the caching of our sample app s entries in order.1 class EntrySweeper 'entries', :action => 'public'6 expire_fragment(%r{entries/.*})7 expire_fragment(:fragment => (entry.user.name + "_stats"))8 end910 alias_method :after_save, :expire_cached_content11 alias_method :after_destroy, :expire_cached_content1213 endOnce you have aSweeperclass (put it in yourapp/modelsdirectory), you need to tell your controller to usethat sweeper in conjunction with its actions.Here s the top of the revised entries controller:1 class EntriesController [:index]4 caches_page :public5 cache_sweeper :entry_sweeper, :only => [:create, :update, :destroy]67.Caching and Performance 436Like many other controller macros, thecache_sweepermethod takes:onlyand:exceptoptions.There s noneed to bother the sweeper for actions that can t modify the state of the application, so we do indeed includethe:onlyoption in our example.Like the relatedobservers,sweepersare not limited to observing just one model.The main thing to rememberif we go down that route is that our callback methods will need to know how to handle all of them.Ruby scasestatement may come in handy, as shown in Listing [lst:17-8], a full revision of theEntrySweeper, whichmay now observeCommentas well asEntryobjects.1 class EntrySweeper 'entries', :action => 'public'6 expire_fragment(r%{entries/.*})78 user = case entry9 when Entry then record.user10 when Comment then record.entry.user11 end1213 expire_fragment(:fragment => (user.name + "_stats"))14 end1516 alias_method :after_save, :expire_cached_content17 alias_method :after_destroy, :expire_cached_content1819 endThe big gotcha with regular expression andexpire_fragmentis that it is not supported with the most commoncaching service used on Rails production systems: Memcached.17.1.7 Cache LoggingIf you ve turned on caching during development, you can actually monitor the Rails log for messages aboutcaching and expiration.1 Processing Entries#index (for 127.1 at 2007-07-20 23:07:09) [GET]2.3 Cached page: /entries.html (0.03949)45 Processing Entries#create (for 127.1 at 2007-07-20 23:10:50) [POST]6.7 Expired page: /entries.html (0.00085)It s a good way to see whether your caching is actually working as expected.Caching and Performance 43717.1 [ Pobierz caÅ‚ość w formacie PDF ]