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 re开发者_JAVA技巧try of a job.
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
Delayed::Worker.new.run(Delayed::Job.last)
This will remove the job after it is done.
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.
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
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!
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
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!}
Delayed::Job.all.each(&:invoke_job)
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.
精彩评论