class MyWorker
include Sidekiq::Worker
sidekiq_options retry: false
end
型 确保worker可预见地引发错误,如下所示:
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
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
2条答案
按热度按时间bttbmeg01#
我不相信有一个很好的答案,因为如果我记得正确的Sidekiq队列使用Redis列表,所以有一个FIFO的期望。重试的作业将在同一队列中排队,因此这意味着它们将始终位于最后。
一种方法不是很好,也不是我推荐的方法,是添加另一个队列,并将作业重试发送到它:
字符串
将工作进程设置为不重试:
型
确保worker可预见地引发错误,如下所示:
型
添加一些逻辑来处理该异常,然后通过新创建的队列再次运行此作业:
型
这意味着任何失败并在
my_worker_retries
队列中排队的作业都可能陷入无限循环-作业失败,被救出,排队,再次失败-更糟糕的是,由于您没有使用Sidekiq内置的重试排队机制,因此没有回退算法来确保重试不会像CPU可以处理的那样快。整个东西都很脆弱。
您可以尝试通过传递一个参数来防止这种情况,该参数指示此作业已重试的次数,以便您可以在某个数字后停止:
型
你可以扩展它来拥有一个你自己的回退算法:
型
所有这些都不是理想的,但它确实回答了这个问题。我当然希望有比这更好的解决方案。
有一些Sidekiq扩展可能会工作,例如https://github.com/chartmogul/sidekiq-priority_queue,但我以前没有使用过它们。
t1qtbnec2#
如果您希望失败的作业在重试时位于队列的 * 开头 *,那么这意味着重试之间的等待时间为
0
。在这种情况下,您应该简单地将作业执行代码的主要部分 Package 在
begin/rescue
块中,然后立即重试。请注意,您还需要一个“退出”,例如。重试固定次数或特定时间间隔,否则中毒消息将导致您的工作进程无限期地处理同一消息(就像其他消息代理将拒绝的消息返回到队列顶部一样,例如RabbitMQ)