Archive for category ruby on rails

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.

No Comments