Archive for March, 2010
Rails Delayed Job
Posted by dyn in ruby on rails on March 25th, 2010
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.