Ruby 将重试的sidekiq作业放在队列的开头

Ruby 将重试的sidekiq作业放在队列的开头,ruby,sidekiq,Ruby,Sidekiq,我有大约100000份工作的sidekiq队列。有些工作失败了,这没关系,因为当sidekiq重试时,它们通常会成功 但是,来自RetrySet的作业被添加到队列的末尾。很长一段时间过去了,直到作业再次被处理 如何将重试的作业放在队列的开头,以便优先处理它们?我不认为有什么好的答案,因为如果我记得右侧的KIQ队列使用Redis列表,那么就需要FIFO。重试的作业将在同一队列中排队,因此这意味着它们将始终位于末尾 有一种方法不是很好,也不是我推荐的方法,那就是添加另一个队列,并将作业重试发送到该队

我有大约100000份工作的sidekiq队列。有些工作失败了,这没关系,因为当sidekiq重试时,它们通常会成功

但是,来自RetrySet的作业被添加到队列的末尾。很长一段时间过去了,直到作业再次被处理


如何将重试的作业放在队列的开头,以便优先处理它们?

我不认为有什么好的答案,因为如果我记得右侧的KIQ队列使用Redis列表,那么就需要FIFO。重试的作业将在同一队列中排队,因此这意味着它们将始终位于末尾

有一种方法不是很好,也不是我推荐的方法,那就是添加另一个队列,并将作业重试发送到该队列:

# config/sidekiq.yml
---
:queues:
  - default
  - my_worker_retries
将工作进程设置为不重试:

class MyWorker
  include Sidekiq::Worker
  sidekiq_options retry: false
end
确保您的工作人员可预测地引发错误,如下所示:

class MyWorker
  include Sidekiq::Worker
  sidekiq_options retry: false

  def perform(arg)
    raise ArgumentError
  end
end
添加一些逻辑来处理该异常,然后通过新创建的队列再次运行此作业:

class MyWorker
  include Sidekiq::Worker
  sidekiq_options retry: false

  def perform(arg)
    begin
      raise ArgumentError
    rescue ArgumentError => error
      MyWorker.set(queue: :my_worker_retries).perform_async(arg)
    end
  end
end
这意味着任何失败并在
my_worker\u retries
队列中排队的作业都可能陷入无限循环——作业失败、获救、排队、再次失败——更糟糕的是,因为您没有使用Sidekiq内置的重试排队机制,没有退避算法来确保重试不会以CPU能够处理的速度启动

整个事情都很脆弱

您可以尝试通过传递一个参数来防止出现这种情况,该参数指示此作业重试了多少次,以便您可以在某个数字后停止:

class MyWorker
  include Sidekiq::Worker
  sidekiq_options retry: false

  MAX_RETRIES = 5

  def perform(arg, retries = 0)
    raise 'Too many retries' if retries >= MAX_RETRIES

    begin
      raise ArgumentError
    rescue ArgumentError => error
      MyWorker.set(queue: :my_worker_retries).perform_async(arg, retries + 1)
    end
  end
end
您可以将其扩展为拥有自己的退避算法:

MyWorker.set(queue: :my_worker_retries).perform_in((retries + 1).hours, arg, retries + 1)
这些都不理想,但它确实回答了这个问题。我当然希望有比这更好的解决办法


例如,有一些Sidekiq扩展可能会起作用,但我以前从未使用过。

我认为您特别要求的东西是不可能的。实际上,如果这些作业具有高优先级,您应该将它们推送到一个单独的队列中。所有作业都具有相同的优先级。只是如果他们失败了并被重试,他们应该优先感谢Anotherm分享你的方法。我宁愿不使用sidekiq重试机制。我害怕讨厌的虫子独自做这件事