Rails Delayed Job


When building a web application, you always try to make it fast and responsive. Sometimes this task can be difficult because of some long running requests like: file uploads, sending email, updating sphinx indexes, running reports, etc.

Enter Delayed Job.

First, we must install the plugin and migrate the delayed_job table that handles the work:

1
script/plugin install git://github.com/collectiveidea/delayed_job.git

Then we create the table:

1
2
script/generate delayed_job
rake db:migrate

Now we are ready to enqueue jobs. Let’s say we want to send an email with delayed_job:

1
2
3
Emailer.deliver_contact(@comments) #old way

Emailer.send_later(:deliver_contact, @comments) #delayed_job way

Now you check your email and you can’t find anything. That’s because we need to run the delayed_job daemon.

1
script/delayed_job start

Now you can see how the daemon sends the email. Instead of the send_later method, you can “mark” a method to always run in background:

1
2
3
4
5
6
7
8
9
class Photo
  def generate_thumbnails
       #generate all the thumbnails
  end
  handle_asynchronously :generate_thumbnails
end

@photo = Photo.new(params[:photo])
@photo.generate_thumbnails #this will run throught delayed_job

Now you need to run delayed_job in your production environment, with  capistrano you should have something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace :delayed_job do
  desc "Start delayed_job process"
  task :start, :roles => :app do
    run "cd #{current_path}; RAILS_ENV=production script/delayed_job start"
  end

  desc "Stop delayed_job process"
  task :stop, :roles => :app do
    run "cd #{current_path}; RAILS_ENV=production script/delayed_job stop"
  end

  desc "Restart delayed_job process"
  task :restart, :roles => :app do
    run "cd #{current_path}; RAILS_ENV=production script/delayed_job restart"
  end
end

after "deploy:start", "delayed_job:start"
after "deploy:stop", "delayed_job:stop"
after "deploy:restart", "delayed_job:restart"

If there’s an error when launching the daemon in production, that might be because you need the daemons gem. I had problems with the daemons 1.0.11 so I went for the ghazel-daemons and everything worked fine.

We highly recommend to use monit to monitor and restart the delayed_job process in case something goes wrong. You can check other options like custom jobs and configuration parameters in the docs.

  1. No comments yet.
(will not be published)
  1. No trackbacks yet.