Mark Gandolfo's Blog
How To Integrate Delayed Job Into Your App
So a quick how to integrate delayed job into your app, since i've found a lot of the tutorials out there leave out some crucial information.
Firstly, I used Tobi's delayed_job since it comes with a few extra bits a pieces, like generators and the like.
Install the plugin
You can either install it using the rails command, or use git submodules (which i won't cover here)
script/plugin install git://github.com/tobi/delayed_job.git
Generate and run the migration
We'll run the generator script to generate our migration and then migrate the database up
script/generate delayed_job_migration
Which will generate a migration that looks like this. Have a read through the file. You're probably asking yourself where the object to be run is stored. Its actually stored in the "handler" field as a sexy yaml field.
create_table :delayed_jobs, :force => true do |table|
table.integer :priority, :default => 0 # Allows some jobs to jump to the front of the queue
table.integer :attempts, :default => 0 # Provides for retries, but still fail eventually.
table.text :handler # YAML-encoded string of the object that will do work
table.string :last_error # reason for last failure (See Note below)
table.datetime :run_at # When to run. Could be Time.now for immediately, or sometime in the future.
table.datetime :locked_at # Set when a client is working on this object
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
table.string :locked_by # Who is working on this object (if locked)
table.timestamps
end
How to queue mail in your app
Lets say for example we have a AccountsMailer
class AccountMailer < ActionMailer::Base
def confirm(user)
subject 'Your account has been created'
recipients user.email
from 'you@email.com'
sent_on Time.zone.now
content_type 'text/html'
body "Welcome Aboard"
end
end
We would normally send an email by doing something like this in our controllers
AccountMailer.deliver_confirm(@user)
With delayed job, we can simply do a
AccountMailer.send_later(:deliver_confirm,@user)
So delayed job adds a send_later class method, which takes an AccountMailer class method as its first param, and then the methods params as the next.
How to send the mail
Setting up actionmailer is outside of the scope of this post. So i'm assuming you have it set up already.
The jobs at this stage are being queued in your database, but we haven't started any sort of job to process the queue. To start the queue simple run
rake jobs:work
You should see the queue starting to process, or at idle if its empty.
This is great, but what happens if the rake task dies for some reason???? Daemons to rescue!!!
Daemonising delayed job queue processor
First install the daemons gem
sudo gem install daemons
Next create a script in your script/ directory.. I called mine delayed_job
#!/usr/bin/env ruby
require 'rubygems'
require 'daemons'
dir = File.expand_path(File.join(File.dirname(__FILE__), '..'))
daemon_options = {
:multiple => false,
:dir_mode => :normal,
:dir => File.join(dir, 'tmp', 'pids'),
:backtrace => true
}
Daemons.run_proc('job_runner', daemon_options) do
if ARGV.include?('--')
ARGV.slice! 0..ARGV.index('--')
else
ARGV.clear
end
Dir.chdir dir
RAILS_ENV = ARGV.first || ENV['RAILS_ENV'] || 'development'
require File.join('config', 'environment')
Delayed::Worker.new.start
end
Save that, and you can now simple do the below to start the queue.
script/delayed_job start
I would recommend reading up on the delayed_job and daemons extensions to understand the inner workings, but at least this is enough to get you up and running!
notes
You can also clear the queue by running
rake jobs:clear
February 19, 2010 at 3:44 AM
This relevant to my interests :)