Remotely flush your page and fragment caches using rake and capistrano
Anton Jenkins | February 26, 2009
The key to this technique is making your cache sweepers easy to call from a rake task. For this website I’ve created a simple site sweeper which flushes the entire page cache :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# app/sweepers/site_sweeper.rb class SiteSweeper < ActionController::Caching::Sweeper observe Page, Post, Comment, Tag, Tagging def after_save(site) self.class::sweep end def after_destroy(site) self.class::sweep end def self.sweep cache_dir = ActionController::Base.page_cache_directory unless cache_dir == RAILS_ROOT+"/public" FileUtils.rm_r(Dir.glob(cache_dir+"/*")) rescue Errno::ENOENT RAILS_DEFAULT_LOGGER.info("Cache directory '#{cache_dir}' fully swept.") end end end |
By declaring the sweep method as a class method we make it easy to call from rake to force a sweep.
To do so we need to create a new rake file :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# lib/tasks/pixellated.rake namespace :pixellated do namespace :cache do desc "Expire the flickr_sidebar fragment cache" task :expire_flickr => :environment do ActionController::Base.new.expire_fragment('flickr_sidebar') RAILS_DEFAULT_LOGGER.info("Flickr sidebar cache swept") end desc "Expire page cache" task :expire_pages => :environment do SiteSweeper.sweep end desc "Expire everything" task :expire_all => [:expire_flickr, :expire_pages] do RAILS_DEFAULT_LOGGER.info("All caches swept") end end end |
The tasks in here allow me to flush the page cache as well as flush the flickr_sidebar fragment which you can see to the right of each page. It takes around 8 seconds to talk to flickr and refresh this page element so it’s a perfect candidate for fragment caching.
We can now use rake to flush the caches from the command line :
1 2 3 |
rake pixellated:cache:expire_flickr rake pixellated:cache:expire_pages rake pixellated:cache:expire_all |
But what about on the production server?
Well that’s your local machine sorted, but we need a way to flush the caches on the live server. Capistrano to the rescue again!
Because we can perform cache flushes using rake we just need a way to invoke the rake tasks on the server. Of course we will need to do a deploy to get our newly created rake tasks on to the server first (very important and easy to forget!) :
1 |
cap deploy |
Now we can add the following capistrano tasks to depoy.rb to invoke these rake tasks remotely :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# config/deploy.rb namespace :pixellated do namespace :cache do set :remote_rake_cmd, "/usr/local/bin/rake" desc "Expire everything" task :expire_all do run("export RAILS_ENV=production; cd #{deploy_to}/current; #{remote_rake_cmd} pixellated:cache:expire_all") end desc "Expire page cache" task :expire_pages do run("export RAILS_ENV=production; cd #{deploy_to}/current; #{remote_rake_cmd} pixellated:cache:expire_pages") end desc "Expire the flickr_sidebar fragment cache" task :expire_flickr do run("export RAILS_ENV=production; cd #{deploy_to}/current; #{remote_rake_cmd} pixellated:cache:expire_flickr") end end end |
Simple. Now if I’ve posted some pictures up to flickr and I want my caches flushed I just run…
1 |
cap pixellated:cache:expire_all |
... and it’s sorted. Plus it uses an existing sweeper used elsewhere in the application, so it’s DRY.
Further reading
Ana Nelson has an entire post on calling rake remotely using capistrano if you are interested in exploring this.











