【问题标题】:Sidekiq transient vs fatal errorsSidekiq 瞬态与致命错误
【发布时间】:2017-02-13 15:53:15
【问题描述】:

有没有办法从 Sidekiq 作业中出错,告诉 Sidekiq“此错误是致命的且不可恢复,不要重试,直接将其发送到死作业队列”?

查看Sidekiq Error Handling 文档,它似乎将所有错误解释为瞬态,并且无论错误类型如何都会重试作业(如果启用了重试)。

【问题讨论】:

标签: ruby sidekiq


【解决方案1】:

你应该挽救那些特定的错误,而不是重新提出它们。

def perform
  call_something
rescue CustomException
  nil
end

编辑:

好吧,如果你想故意向 DLQ/DJQ 发送消息,你需要创建一个方法来完成 #send_to_morgue 所做的事情。我敢肯定 Mike Perham 会来这里对我的建议大喊大叫,但是......

    def send_to_morgue(msg)
      Sidekiq.logger.info { "Adding dead #{msg['class']} job #{msg['jid']}" }
      payload = Sidekiq.dump_json(msg)
      now = Time.now.to_f
      Sidekiq.redis do |conn|
        conn.multi do
          conn.zadd('dead', now, payload)
          conn.zremrangebyscore('dead', '-inf', now - DeadSet.timeout)
          conn.zremrangebyrank('dead', 0, -DeadSet.max_jobs)
        end
      end
    end

您必须深入了解 msg 进入该方法的唯一区别,但我怀疑它通常会在解析之前命中中间件。

【讨论】:

  • nil 是多余的 :)
  • @mudasobwa 同意,但我把它放在那里,所以它很明确
  • 不幸的是,这不会将消息发送到死作业队列,这是我想要的“致命”错误工作流的重要组成部分。
  • 我错过了@mtulio 的那部分,感谢您的澄清。可悲的是#send_to_morgue 方法是私有的
【解决方案2】:

如果在GitHub 上找到解决您问题的方法。在那篇文章中,他们建议编写一个自定义中间件来处理您想要防止重试的异常。这是一个基本示例:

def call(worker, msg, queue)
  begin
    yield
  rescue ActiveRecord::RecordNotFound => e
    msg['retry'] = false
    raise
  end
end

你可以扩展你得到的:

def call(worker, msg, queue)
  begin
    yield
  rescue ActiveRecord::RecordNotFound => e
    msg['retry'] = false
    raise
  rescue Exception => e
    if worker.respond_to?(:handle_error)
      worker.handle_error(e)
    else
      raise
    end
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-19
    • 2012-05-16
    • 2016-07-14
    • 1970-01-01
    • 2022-01-15
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多