Rack::CacheBuster Contest finalist
About
Make all ETags code revision number specific, and gradually align all expiry times to a single point in time.
Details
So your content expires in an hour. How the hell can you deploy cleanly?
"So this middleware disables the cache?" you ask. "No" I respond. That would be dumb.
This middleware makes all ETags code revision number specific, and gradually aligns all expiry times to a single point in time.
So you tell the server you are going to deploy in an hour, it makes sure all clients have forgotten their cache in an hour, and then when you deploy the ETags change, so they will get fresh content.
By sitting it in front of Rack::Cache your app will see no more dynamic hits than it did before! Rack::CacheBuster only invalidates the cache on the clients, so Rack::Cache still has a valid for the duration of the wind down!
And for bonus points, I've even given you some cap tasks, and a Rails specific helper!
Usage
Rack::CacheBuster
Use to wind down a running app when needed.
Limits the max-age to the contents of the WIND_DOWN file, and salts the ETags to unsure clients see different deployments as having different contents.
Usage:
require "rack/cache_buster"
…
use Rack::CacheBuster, APP_VERSION, WIND_DOWN_TIME
Rails Usage:
require "rack/cache_buster"
…
use Rack::CacheBuster::Rails
Before you deploy (capistrano):
Add this to your deploy.rb:
begin
gem "rack-cache-buster"
require 'rack_cache_buster_recipes'
rescue LoadError
puts "\n\n*** Please gem install rack-cache-buster before trying to deploy.\n\n"
end
# set :wind_down_time, 60*60 # defaults to 1hr
Then:
cap cache:winddown
… wait 1 hr …
cap deploy:migrations
… profit!
Before you deploy (other):
Find the maximum cache duration for all pages in your app, start this process with at least that amount time before you deploy.
Create a WIND_DOWN file in the app root of all your app servers.
Restart all instances (touch tmp/restart.txt will be fine for passenger apps).
Once all the caches should have expired you can deploy as normal.
Notes
If you are using Rack::Cache, you can safely put the CacheBuster below it in the stack, but only if you clear Rack::Cache's cache upon deploy.
This is actually the recommended approach as it will prevent the increased amount of hits between WIND_DOWN_TIME and your actual deployment from making it through to your app.
