在Delayed_job中手动重试作业


70

Delayed :: Job的自动重试功能很棒,但是现在有一项我想手动重试的工作。有没有一种方法可以像我这样调用工作本身?

Delayed::Job.all[0].perform

或跑步或其他。我尝试了一些事情,并整理了文档,但是不知道如何执行作业的手动重试。


3
Delayed::Worker.new.run(Delayed::Job.first) 裁判
杰克·伯杰

Answers:


106

手动呼叫工作

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

如果作业成功运行,这不会删除该作业。您需要手动将其删除:

Delayed::Job.find(10).destroy

10
@joe建议的替代方法是更好的安全方法,尤其是在作业需要知道它是在脚本/控制台中还是在作业运行程序中运行时。尝试使用此方法将作业排队以便立即重试Delayed :: Job.first.update_attributes(:attempts => 0,:run_at => Time.now,:failed_at => nil,:locked_by => nil,:locked_at => nil)
so_mv 2012年

8
attempts无法分配,update_attributes因为它是受保护的属性。我只是这样做:dj = Delayed::Job.first; dj.run_at = Time.now; dj.attempts = 0; dj.save!;
Anjan 2012年

要做到这一点,可以工作(大约100个工作)。Delayed :: Job.where.all.each {| dj | dj.run_at = Time.now; dj.attempts = 0; dj.save!}
tobinharris

1
我就是这么做的Delayed::Job.where.not(last_error: nil).update_all(run_at: Time.current)
Jason Galuten

last_error如果作业失败,这不会设置属性
localhostdotdev

33
Delayed::Worker.new.run(Delayed::Job.last)

完成后将删除该作业。


即使失败,它也会将其删除
aledustet '16

对于所有延迟的工作,您都可以做Delayed::Job.find_each(batch_size: 100) { |d| Delayed::Worker.new.run(d) }
MatayoshiMariano,2017年

1
@aledustet当然不是。你积极吗?
约书亚·品特

这为我工作,并取得了成功。没有尝试过失败的尝试,但我真的怀疑它会删除它,这将非常令人惊讶。
dzajic

12

通过找到工作并执行绩效,您可以按照您所说的完全做到这一点。

但是,我通常要做的只是将run_at设置回去,以便作业处理器再次将其拾取。


1
没有perform延迟工作对象的方法。最接近的是Delayed::Job.find(10).payload_object.perform,并且不应使用该值。
lulalala 2012年

10

我在控制器中有一个方法用于测试目的,当我点击URL时,该方法只会重置所有延迟的作业。不是超级优雅,但对我来说很棒:

# 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

1
您不能使用update_all ebcause尝试受保护的属性
Ivailo Bardarov

3
update_all直接使用SQL,因此不会调用验证(或受保护的属性等)
迈克尔

8

上面的先前答案可能已过时。我发现我需要将failed_at,locked_by和locked_at设置为nil:

(对于您要重试的每个作业):

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!

5

如果延迟的作业失败,需要重新运行,则只需选择它们,并将引用失败的重试的所有内容设置为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

4

在开发环境中,rails console按照Joe Martinez的建议,通过重试所有延迟的工作的好方法是:

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

6
run_at在4.0.1中更新似乎还不够。我必须执行以下操作:Delayed::Job.where("failed_at is not null").each do |dj| dj.run_at = Time.now; dj.last_error = nil; dj.failed_at = nil; dj.save! end
牛排追逐者2014年


1

把它放在一个初始化文件中!

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

那你就可以跑 Delayed::Job.find(1234).retry!

基本上,这会将作业重新放入队列并正常处理。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.