我不希望活动作业在失败时删除作业。我希望有机会修复故障,然后让它们重新运行。我试着这样做:
class ApplicationJob < ActiveJob::Base
retry_on Exception, attempts: Float::INFINITY
end
,但它没有工作。一个邮件任务失败了,被丢弃了。我使用delayed_job作为实现。
你知道怎么做吗?
如果您使用的是Delayed::Job,那么最终会有两个相互叠加的重试机制。Active Job, Rails通用实现,和Delayed::Job.
For Active::Job you can do:
class ApplicationJob < ActiveJob::Base
retry_on Exception, wait: :exponentially_longer, attempts: Float::INFINITY
end
如果没有wait: :exponentially_longer
,您可能会以每3秒尝试大量作业告终。
如果您使用的是Delayed::Job,则此重试方法的行为可能有点奇怪。作业运行并且似乎成功了,但是由于它失败了,ActiveJob创建一个新的作业稍后运行。因此,delay::Job中的字段attempts
保持为0,您需要查看字段handler
以查看它运行了多少次。
一个ActiveJob最后一次失败,这个异常会出现在Delayed::Job,它有自己的重试机制。延迟:作业默认重试25次,然后删除作业。
要使延迟作业永远保持尝试,您可以创建一个初始化文件config/initializers/delayed_job_config.rb
,更改max_attempts
的值:
Delayed::Worker.max_attempts = Float::INFINITY
如果您担心丢失作业,可以通过设置:
Delayed::Worker.destroy_failed_jobs = false
您使用哪一个,或者如何混合使用它们取决于您。使用Delayed::Job's使数据库更有意义,使用ActiveJob's意味着该方法可以传输到其他实现。
retry_on exception, attempts::unlimited (Rails 7.0+)
从Rails 7.0开始,ActiveJob
支持将attempts: :unlimited
传递给retry_on
方法的能力:
:attempts
-重新排队作业指定的次数(默认:5次)或符号引用:unlimited
重试作业,直到成功
例如:
class RemoteServiceJob < ActiveJob::Base
# ...
retry_on CustomInfrastructureException, wait: 5.minutes, attempts: :unlimited
def perform(*args)
# ...
end
end
来源:
- ActiveJob:例外::类方法# retry_on。
- retry_on参数尝试现在接受:无限制。 Rails的新特性
我们可以通过在retry_on文档
之后将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
应该可以了
retry_on Exception, wait: 5。分钟,尝试数::unlimited
https://edgeapi.rubyonrails.org/classes/ActiveJob/Exceptions/ClassMethods.html