Manually Retry Job in Delayed_job

Delayed::Job's auto-retry feature is great, but there's a job that I want to manually retry now. Is there a method I can call on the job itself like...

Delayed::Job.all[0].perform

or run, or something. I tried a few things, and combed the documentation, but couldn't figure out how to execute a manual retry of a job.

43128 次浏览

You can do it exactly the way you said, by finding the job and running perform.

However, what I generally do is just set the run_at back so the job processor picks it up again.

To manually call a job

Delayed::Job.find(10).invoke_job # 10 is the job.id

This does not remove the job if it is run successfully. You need to remove it manually:

Delayed::Job.find(10).destroy

I have a method in a controller for testing purposes that just resets all delayed jobs when I hit a URL. Not super elegant but works great for me:

# For testing purposes
def reset_all_jobs
Delayed::Job.all.each do |dj|
dj.run_at = Time.now - 1.day
dj.locked_at = nil
dj.locked_by = nil
dj.attempts = 0
dj.last_error = nil
dj.save
end
head :ok
end

In a development environment, through rails console, following Joe Martinez's suggestion, a good way to retry all your delayed jobs is:

Delayed::Job.all.each{|d| d.run_at = Time.now; d.save!}

Prior answers above might be out of date. I found I needed to set failed_at, locked_by, and locked_at to nil:

(for each job you want to retry):

d.last_error = nil
d.run_at = Time.now
d.failed_at = nil
d.locked_at = nil
d.locked_by = nil
d.attempts = 0
d.failed_at = nil # needed in Rails 5 / delayed_job (4.1.2)
d.save!
Delayed::Job.all.each(&:invoke_job)
Delayed::Worker.new.run(Delayed::Job.last)

This will remove the job after it is done.

if you have failed delayed job which you need to re-run, then you will need to only select them and set everything refer to failed retry to null:

Delayed::Job.where("last_error is not null").each do |dj|
dj.run_at = Time.now.advance(seconds: 5)
dj.locked_at = nil
dj.locked_by = nil
dj.attempts = 0
dj.last_error = nil
dj.failed_at = nil
dj.save
end

Put this in an initializer file!

module Delayed
module Backend
module ActiveRecord
class Job
def retry!
self.run_at = Time.now - 1.day
self.locked_at = nil
self.locked_by = nil
self.attempts = 0
self.last_error = nil
self.failed_at = nil
self.save!
end
end
end
end
end

Then you can run Delayed::Job.find(1234).retry!

This will basically stick the job back into the queue and process it normally.