微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

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

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

但是没有用。电子邮件作业失败并被丢弃。我使用 delay_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 来实现自己的重试逻辑

可能有自己的重试机制或将其放入等待队列中进行检查。

如果自定义逻辑的重试尝试失败,您还可以传递一个将被调用的块,而不是让异常冒泡。这个块是以作业实例作为第一个参数,错误实例作为第二个参数产生的。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。