Work
About
Contact

Capistrano and Whenever with multiple servers/nodes

June 25, 2012   |   Tech
Agile League

Sometimes you have different cron jobs that you want run on different node. In our case, we needed to run Sphinx re-indexing on one node, but all our other cron jobs on a separate node. It took a bit of work to do, but here’s how to accomplish it with Capistrano and Whenever.

Update: Nov 2012 Whenever has released a new version of the gem that natively supports role definition. So, the rest of this post is no longer necessary. Just upgrade to anything over 0.8.0 and you’re good to go. Yay!
For posterity…
In deploy.rb

# This sets an empty list of roles so whenever won't run the default tasks
set "whenever_roles", []
# Create cap tasks to set the role as a command line variable passed to whenever
before  "deploy:finalize_update", "whenever:update_crontab_asynch"
before  "deploy:finalize_update", "whenever:update_crontab_db"
namespace :whenever do
  task :update_crontab_asynch, :roles => [:asynch] do
    run "cd #{release_path} && RAILS_ENV=#{stage} bundle exec whenever --update-crontab my_app --set \"environment=#{stage}&role=asynch\""
  end
  task :update_crontab_db, :roles => [:db] do
    run "cd #{release_path} && RAILS_ENV=#{stage} bundle exec whenever --update-crontab my_app --set \"environment=#{stage}&role=db\""
  end
end

In schedule.rb

# Put your different tasks inside if blocks that use the command line "role" variable
if @role == "db"
  every :wednesday, :at => "07:07" do
    rake "ts:in"
  end
end
if @role == "asynch"
  every 1.hour, :at => 22 do
    runner "CalendarEvent.send_reminders"
  end
end

This isn’t really recommended by the capistrano team, as many capistrano setups don’t necessarily correlate roles to nodes one-to-one, and it could be that a node has multiple roles. However, if you do have one-to-one, or at least non-conflicting nodes, this is an easy way to partition your cron jobs.
For reference, this is working with:

  • Rails 3.0.12
  • Ruby 1.9.3
  • Capistrano gem 2.12.0
  • Whenever gem 0.7.3