litany against fear

coding with spice ¤ by nick quaranto

Load Rails conditionally with Rack

published 10 Nov 2009

One of the great things about Gemcutter is that it’s using Sinatra via Rails Metal to serve up the gems. Recently, I had to run some long migrations (~10 minutes) and I’m sure we’ll have some more in the future. Since the gem server is decoupled from the Rails app, some clever Rack loading now allows us to continue to serve gems even when we’re down for maintenance.

The now looks like this:

  require File.join('vendor', 'bundler_gems', 'environment')
  require File.join('config', 'environment')
  use Rack::Static,
    :urls => ["/index.html",
    :root => "public/maintenance"
  use Hostess
  use Rack::Maintenance,
    :file => File.join('public', 'maintenance', 'index.html')
  run Sinatra::Application
  require 'thin'
  run => ENV['RAILS_ENV'])

So now, Heroku treats Gemcutter as a Rack app, and not a pure Rails app. Normally, it’ll just use Thin and boot up Rails as normal with Rack::Adapter::Rails. script/server still works as normal, too, but I’ll probably use shotgun instead.

The fun begins when you run MAINTENANCE_MODE=on rackup. The following happens from there:

  • Load up the Bundler environment that has all of our gems, and some of Rails’ magic.
  • Fire up Rack::Static to serve static assets like the images and CSS to make the site look nice
  • Use the Hostess, Gemcutter’s Sinatra gem server to continue to serve gems
  • All other requests are then caught by David Dollar’s rack-maintenance that simply serves up a static HTML page.
  • Use Sinatra::Application since we need some sort of endpoint.

And boom, we have a read-only site that continues to serve gems. Rack rules.

email twitter github