如何让 Active Job 永远重试所有作业?

How do I make Active Job retry all jobs forever?

我不希望活动作业在失败时丢弃作业。我想有机会修复故障然后让他们重新运行。我试过这样做:

class ApplicationJob < ActiveJob::Base
  retry_on Exception, attempts: Float::INFINITY
end

但是没用。电子邮件作业失败并被丢弃。我正在使用 delayed_job 作为实现。

有什么办法吗?

如果您使用的是 Delayed::Job,您最终会得到两个重试机制。 Active Job,Rails 通用实现,以及 Delayed::Job.

对于 Active::Job 你可以这样做:

class ApplicationJob < ActiveJob::Base
  retry_on Exception, wait: :exponentially_longer, attempts: Float::INFINITY
end

如果没有 wait: :exponentially_longer,您可能会每 3 秒尝试大量作业。

如果您使用 Delayed::Job,此重试方法的行为可能会有点奇怪。作业 运行 似乎成功了,但由于它失败了,ActiveJob 稍后会为 运行 创建一个新作业。因此,Delayed::Job 中的字段 attempts 保持为 0,您需要查看字段 handler 以查看它是 运行.

的次数

一个 ActiveJob 最后一次失败,异常冒泡到 Delayed::Job 它有自己的重试机制。 Delayed::Job 默认 retries 25 times and then deletes the job.

要让延迟作业一直尝试下去,您可以创建一个初始化文件 config/initializers/delayed_job_config.rb 更改 max_attempts 值:

Delayed::Worker.max_attempts = Float::INFINITY

如果您担心失去工作,工作可以失败并且不会通过设置被删除:

Delayed::Worker.destroy_failed_jobs = false

您使用两者中的哪一个,或者如何混合它们取决于您。使用 Delayed::Job 使数据库更有意义,使用 ActiveJob 意味着该方法可以传输到其他实现。

我们可以通过在 retry_on Documentation

之后将 block 传递给 retry_on 来实现自己的重试逻辑

may have its own retry mechanism or place it in a holding queue for inspection.

You can also pass a block that'll be invoked if the retry attempts fail for custom logic rather than letting the exception bubble up. This block is yielded with the job instance as the first and the error instance as the second parameter.

retry_on Exception do |job, error|
  MyJob.perform_later(job)
end

无限重试的工作示例:

# test_job.rb

require 'active_record'
require 'active_support'
require 'active_job'
require 'globalid'

ActiveJob::Base.queue_adapter = :async
GlobalID.app = 'app'
logger = ActiveJob::Base.logger

class ProcessPhotoJob < ActiveJob::Base
  retry_on ActiveRecord::RecordNotFound do |job, error|
    logger.info " retrying job #{job}"
    ProcessPhotoJob.perform_later(job)
  end

  def perform
    logger.info ' performing, but getting error:'
    raise ActiveRecord::RecordNotFound
  end
end

ProcessPhotoJob.perform_later

while true
  sleep 1
end

可以 运行 与:

ruby test_job.rb

这应该有效

retry_on 异常,等待:5.minutes,尝试::无限制

https://edgeapi.rubyonrails.org/classes/ActiveJob/Exceptions/ClassMethods.html