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

pup*_*eno 3 ruby-on-rails rails-activejob ruby-on-rails-6

我不希望活跃的工作在失败时放弃工作。我希望有机会修复故障,然后让它们重新运行。我尝试这样做:

class ApplicationJob < ActiveJob::Base
  retry_on Exception, attempts: Float::INFINITY
end
Run Code Online (Sandbox Code Playgroud)

但它没有用。电子邮件作业失败并被丢弃。我使用 delay_job 作为实现。

任何想法如何做到这一点?

eux*_*eux 5

如果您使用的是 Delayed::Job,您最终会得到两个相互叠加的重试机制。Active Job、Rails 一般实现和 Delayed::Job。

对于 Active::Job,您可以执行以下操作:

class ApplicationJob < ActiveJob::Base
  retry_on Exception, wait: :exponentially_longer, attempts: Float::INFINITY
end
Run Code Online (Sandbox Code Playgroud)

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

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

一个 ActiveJob 最后一次失败,异常冒泡到 Delayed::Job,它有自己的重试机制。Delayed::Job 默认重试 25 次,然后删除 job

为了让延迟作业永远继续尝试,您可以创建一个初始化文件来config/initializers/delayed_job_config.rb更改max_attempts值:

Delayed::Worker.max_attempts = Float::INFINITY
Run Code Online (Sandbox Code Playgroud)

但是,如果您担心失去工作,则工作可能会失败并且不会通过设置删除:

Delayed::Worker.destroy_failed_jobs = false
Run Code Online (Sandbox Code Playgroud)

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