Ruby on rails 如何处理';记录不存在';错误并阻止后台作业尝试重试?

Ruby on rails 如何处理';记录不存在';错误并阻止后台作业尝试重试?,ruby-on-rails,error-handling,rails-activejob,Ruby On Rails,Error Handling,Rails Activejob,Rails应用程序具有调用服务对象的后台作业,如下所示 class ObjectUpdateJob < ActiveJob::Base queue_as :default def perform(object_id) ObjectUpdater.call(object_id) end end class ObjectUpdater def self.call(*args) if @object = Object.find( args[:object_i

Rails应用程序具有调用服务对象的后台作业,如下所示

class ObjectUpdateJob < ActiveJob::Base
  queue_as :default

  def perform(object_id)
    ObjectUpdater.call(object_id)
  end
end

class ObjectUpdater

  def self.call(*args)
    if @object = Object.find( args[:object_id] )
      #... update some stuff from external services 
    else 
      #... raise an error and prevent the background job from attempting to retry
    end
  end
end
class ObjectUpdateJob
这可能是一个简单的问题,但我在错误处理方面的经验有限,如果您能再考虑一下,我将不胜感激


处理此“记录不存在”情况的“Rails方法”是什么,并确保后台作业得到通知,以便不尝试重试?

您可以在工作人员的
执行
操作中加入一个保护子句:

class ObjectUpdateJob < ActiveJob::Base
  queue_as :default

  def perform(object_id)
    return unless Object.find(object_id)
    ObjectUpdater.call(object_id)
  end
end

这样,您就不会让不存在的对象被处理。

如果您使用Sidekiq,您可以将一个标志设置为
:retry=>false
,这样作业就不会自动重试

此外,Sidekiq还内置了错误处理机制。以下是关于此事的更多信息:


希望对您有所帮助。

您可以轻松地以rails的方式处理异常。但不知道如何防止作业重试。我没有看到它的任何文档。该对象可能在排队后被删除,因此最好同时选中两个checksHanks@AndreyDeineko,这很有用。如果你能回答一些问题来帮助我理解这一点,我将不胜感激。(1) 在这种情况下,调用
fail-ActiveRecord::RecordNotFound'string'
与调用
fail'string'
相比,有哪些优点/缺点?(2) 您建议调用一个服务对象,它启动一个后台作业,调用一个服务对象。这是常见的吗?我担心这会给代码增加混乱?(3) 我以前从未遇到过
=Struct.new(:id)
。它似乎替换了
初始化
方法。这是正确的吗?您能指出任何文档吗?谢谢@而且哈维也不确定,对我来说,失败总是足够的。。2) 你是对的,我错了,我不知道我在想什么。你完全正确,不要这样做。但是它的思想很简单,只需在调用worker的地方创建一个guard子句,比如
ObjectUpdateJob.perform\u now(object\u id)if object.find(object\u id)
。这+在
perform
中有return语句应该足以不处理不存在的记录。3) 是的,这对于诸如服务对象之类的东西非常有用。另一个选项是覆盖
ActiveJob::Core
s
initialize
方法,将
fail
放在那里。你可以考虑,但你知道,修补栏杆似乎不是超级清洁。solution@AndyHarvey让我知道,如果我能帮助你进一步感谢@rii,我真正想要的是一种在非常特殊的情况下防止退休的方法,而不是在全球范围内。e、 例如
sidekiq\u选项:retry=>false,除非Object.find(args[:Object\u id])
。有什么想法吗?
ObjectUpdateJob.perform_now(object_id) if Object.find(object_id)