Daemon of resque workers
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
docs
example
exe
gemfiles
lib
script
spec
.gitignore
.rspec Initial set up. Aug 7, 2013
.travis.yml
CHANGES.md v0.8.4 Feb 7, 2018
Gemfile
Guardfile fail fast in guard. Dec 19, 2013
MIT-LICENSE
README.md Describe the `PWD` thing Mar 20, 2015
Rakefile
resqued.gemspec

README.md

resqued - a long-running daemon for resque workers.

Resqued is a multi-process daemon that controls and monitors a pool of resque workers. It works well with slow jobs and continuous delivery.

travis status

Installation

Install by adding resqued to your Gemfile

gem 'resqued'

Run resqued with a config file, like this:

resqued config/resqued.rb

Or like this to daemonize it:

resqued -p tmp/pids/resqued-master.pid -D config/resqued.rb

Configuring workers

Let's say you were running workers like this:

rake resque:work QUEUE=high        &
rake resque:work QUEUE=high        &
rake resque:work QUEUE=slow        &
rake resque:work QUEUE=medium      &
rake resque:work QUEUE=medium,low  &

To run the same fleet of workers with resqued, create a config file config/resqued.rb like this:

2.times { worker 'high' }
worker 'slow'
worker 'medium'
worker 'medium', 'low'

Another syntax for workers:

worker_pool 5
queue 'low', :percent => 20
queue 'normal', :percent => 60
queue '*'

This time, you'd end up with something similar to this:

rake resque:work QUEUE=low,normal,* &
rake resque:work QUEUE=normal,*     &
rake resque:work QUEUE=normal,*     &
rake resque:work QUEUE=*            &
rake resque:work QUEUE=*            &

worker and worker_pool accept a hash of options that will be passed to Resqued::Worker. The supported options are:

  • :interval - The interval to pass to Resque::Worker#run.

Launching in production.

Resqued restarts when its master process receives SIGHUP. It restarts by re-execing the command that you initially ran. There are two main recommendations for running in production.

  • If you use bundler to install resqued, tell it to generate a binstub for resqued. Invoke this binstub (e.g. bin/resqued) when you start resqued.

  • Specify a pid file using the -p option. This pidfile will have the PID of the master process. See docs/signals.md for more information about which signals are supported.

If your application is running from a symlinked dir (for example, capistrano's "current" symlink), you'll need to do two more things:

  • Ensure that your resqued master process is at least 0.7.13 (ps o args= $RESQUED_MASTER_PID should start with "resqued-0.7.13" or higher).

  • Explicitly set the BUNDLE_GEMFILE environment variable to the symlink dir of your app.

  • If you're invoking resqued from something that resolves symlinks in pwd, you'll also want to explicitly set the PWD environment variable.

Rolling all of the above advice together, here's a sample that you could use in an upstart script for resqued:

# fragment of /etc/init/resqued.conf

kill signal QUIT

env BUNDLE_GEMFILE=/opt/app/current/Gemfile
env PWD=/opt/app/current
chdir /opt/app/current

exec bin/resqued -c config/resqued.rb -p /opt/app/shared/tmp/pids/resqued.pid

Compatibility with Resque

Resqued does not automatically split comma-separated lists of queues in environment variables like Resque does. To continue using comma-separated lists, split them in your resqued config file:

queue (ENV["QUEUE"] || "*").split(',')

Loading your application

An advantage of using resqued (over rake resque:work) is that you can load your application just once, before forking all the workers.

For a Rails application, you might do this:

before_fork do
  require "./config/environment.rb"
  Rails.application.eager_load!
  # `before_fork` runs in the Listener, and it doesn't actually run any application code.
  ActiveRecord::Base.connection.disconnect!
end

after_fork do |resque_worker|
  # Set up a new connection to the database.
  ActiveRecord::Base.establish_connection
  # `resque_worker.reconnect` already happens
end

Customizing Resque::Worker

You can configure the Resque worker in the after_fork block

after_fork do |resque_worker|
  # Do not fork to `perform` jobs.
  resque_worker.cant_fork = true

  # Wait a loooong time on SIGTERM.
  resque_worker.term_timeout = 1.day

  resque_worker.run_at_exit_hooks = true

  Resque.before_first_fork do
    # ...
  end
end

Full config file example

worker 'high'
worker 'low', :interval => 30

worker_pool 5, :interval => 1
queue 'high', 'almosthigh'
queue 'low', :percent => 20
queue 'normal', :count => 4
queue '*'

before_fork do
  require "./config/environment.rb"
  Rails.application.eager_load!
  ActiveRecord::Base.connection.disconnect!
end

after_fork do |worker|
  ActiveRecord::Base.establish_connection
  worker.term_timeout = 1.minute
end

In this example, a Rails application is being set up with 7 workers:

  • high
  • low (interval = 30)
  • high, almosthigh, low, normal, * (interval = 1)
  • high, almosthigh, normal, * (interval = 1)
  • high, almosthigh, normal, * (interval = 1)
  • high, almosthigh, normal, * (interval = 1)
  • high, almosthigh, * (interval = 1)

Multiple configurations

If your app has several work machines, each with the same application code but different sets of workers, you might want to have a shared config file for the before_fork and after_fork blocks. You can pass in several config files, and resqued will act as if you concatenated them.

$ resqued config/shared.rb config/pool-a.rb
$ resqued config/shared.rb config/pool-b.rb

Testing

To test your resqued configuration, add a test case like this:

class MyResquedTest < Test::Unit::TestCase
  include Resqued::TestCase
  def test_resqued_config
    assert_resqued 'config/resqued.rb'
  end
end

See also

For information about how resqued works, see the documentation.