Reputation: 4920
Delayed::Job serializes your class, method & parameters into the handler field. We currently resort to hardcoding this serialized method into our code. This is gross.
How should we be constructing the handler so we can look up an existing queued up job?
Upvotes: 7
Views: 5411
Reputation: 64363
This what I do:
1) Add two new columns to delayed_jobs
table
db/migrations/20110906004963_add_owner_to_delayed_jobs.rb
class AddOwnerToDelayedJobs < ActiveRecord::Migration
def self.up
add_column :delayed_jobs, :owner_type, :string
add_column :delayed_jobs, :owner_id, :integer
add_index :delayed_jobs, [:owner_type, :owner_id]
end
def self.down
remove_column :delayed_jobs, :owner_type
remove_column :delayed_jobs, :owner_id
end
end
2) Add a polymorphic association to Delayed::Job
model
config/initializers/delayed_job.rb
class Delayed::Job < ActiveRecord::Base
belongs_to :owner, :polymorphic => true
attr_accessible :owner, :owner_type, :owner_id
end
3) Monkey patch ActiveRecord::Base
to contain a jobs association
config/initializers/active_record.rb
class ActiveRecord::Base
has_many :jobs, :class_name => "Delayed::Job", :as => :owner
def send_at(time, method, *args)
Delayed::Job.transaction do
job = Delayed::Job.enqueue(Delayed::PerformableMethod.new(self,
method.to_sym, args), 10, time)
job.owner = self
job.save
end
end
def self.jobs
# to address the STI scenario we use base_class.name.
# downside: you have to write extra code to filter STI class specific instance.
Delayed::Job.find_all_by_owner_type(self.base_class.name)
end
end
4) Triggering a jobs
class Order < ActiveRecord::Base
after_create :set_reminders
def set_reminders
send_at(2.days.from_now, :send_email_reminder)
end
def send_email_reminder
end
# setting owner for handle_asynchronously notation.
def foo
end
handle_asynchronously :foo, :owner => Proc.new { |o| o }
end
5) Inspecting jobs
Order.jobs # lists all the running jobs for Order class
order1.jobs # lists all the running jobs for Order object order1
Upvotes: 16