【问题标题】:How do I make Active Job retry all jobs forever?如何让活动作业永远重试所有作业?
【发布时间】:2021-02-21 18:32:09
【问题描述】:

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

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

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

有什么办法吗?

【问题讨论】:

  • 看起来它应该可以工作:github.com/rails/rails/blob/…你有什么错误吗?
  • 你用什么适配器?
  • @HubertJakubiak:我的 SMTP 配置错误,一次尝试后作业就会被丢弃。
  • @HubertJakubiak:我正在使用延迟工作。
  • “电子邮件作业失败” 问题可能是电子邮件作业不使用 ApplicationJob,因此您的代码没有影响它们。您的代码可能会以其他方式工作,只是不适用于电子邮件工作。

标签: ruby-on-rails ruby-on-rails-6 rails-activejob


【解决方案1】:

如果您使用 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 意味着可以将方法传输到其他实现。

【讨论】:

    【解决方案2】:

    我们可以通过在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
    

    【讨论】:

      【解决方案3】:

      这应该可以工作

      retry_on 异常,等待:5 分钟,尝试::无限

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-19
        • 2018-06-02
        • 1970-01-01
        • 2016-05-03
        • 2015-08-27
        • 2015-01-17
        相关资源
        最近更新 更多