如何在不引发错误的情况下将 sidekiq task/job 标记为重试?

How to mark a sidekiq task/job for retry without raising an error?

我使用 Sidekiq 队列来处理与不可靠的第 3 方的通信 API。由于此 API 经常一次宕机几分钟,然后又重新启动,因此 Sidekiq 非常方便。当发生连接问题时,会引发错误,Sidekiq 会将作业放回队列中,以便稍后在一段时间后重试。

我使用 NewRelic 不仅可以帮助调试崩溃,还可以用于监控。我的问题是上述当前方法会在 NewRelic 中产生错误。如果第 3 方 API 停机超过几分钟,错误计数累积到足以导致通过 NewRelic 发送通知。

我想做的是仅当某个作业发生一定次数的重试时才从我的工作人员那里引发错误。我正在使用 sidekiq_retries_exhausted 来执行此操作。我的问题是我不太确定如何在作业出错后将作业放回队列中而不引发错误。

Sidekiq 是否为 return 作业提供任何设施到队列中,增加作业的重试次数,并让它坐在那里直到它再次到期 运行 ,就好像一个工人 class?

中出现异常

您提出了一个特定的错误并告诉错误服务忽略该类型的错误。对于 NewRelic:

https://docs.newrelic.com/docs/agents/ruby-agent/installation-configuration/ruby-agent-configuration#error_collector.ignore_errors

以下是我为防止 AirBrake 出现故意重试错误所做的工作:

class TaskWorker
  include Sidekiq::Worker

  class RetryNotAnError < RuntimeError
  end

  def perform task_id
    task = Task.find(task_id)
    task.do_cool_stuff

    if task.finished?
      @log.debug "Task #{task_id} was successful."
      return false
    else
      @log.debug "Task #{task_id} will try again later."
      raise RetryNotAnError, task_id
    end
  end
end

告诉 Airbrake 忽略它:

Airbrake.configure do |config|
  config.ignore << 'RetryNotAnError'
end

最好让您的异常名称明显不是错误(例如 RetryLaterNotAnError),因为它仍会出现在日志等中,并且您不想在人们看到一堆异常时吓坏他们。

ps。也就是说,我真的希望看到 Sidekiq 提供一个明确的、无错误的重试机制。

如果使用 Sidekiq Enterprise,另一种选择可能是使用一组可选的附加错误类型,然后这些错误类型将被视为 Sidekiq::Limiter::OverLimit 违规。

出于我的目的,我使用了一个新错误 class,然后将其添加到配置中的列表中。以下是 sidekiq-ent 代码(不在 public sidekiq 存储库中)关于如何修改配置文件的说明:

    # An optional set of additional error types which would be
    # treated as a rate limit violation, so the job would automatically
    # be rescheduled as with Sidekiq::Limiter::OverLimit.
    #
    # Sidekiq::Limiter.errors << MyApp::TooMuch
    # Sidekiq::Limiter.errors = [Foo::Error, MyApp::Limited]

在特定作业you can specify the max_retries内,否则默认为20:

sidekiq_options max_limiter_retries: 10

在工作中,我将挽救我不想完全忽略的“预期”间歇性错误,然后提出我已添加到列表中的错误,如下所示:

rescue RestClient::RequestTimeout => e
  raise SidekiqSoftRetry.new(e.inspect)
end

这是我的初始化文件中的内容 -- Mike Perham kind enough to respond 可以选择更新全局重试限制。

class SidekiqSoftRetry < RuntimeError
end
Sidekiq::Limiter::DEFAULT_OPTIONS[:reschedule] = 10
Sidekiq::Limiter.configure do |config|
  config.errors.concat(
    [   
      SidekiqSoftRetry,
    ]
  )
end