Sidekiq在工作中重试计数

时间:2014-04-14 16:40:34

标签: ruby jobs sidekiq

有没有办法获得当前工作的重试次数?

我希望x重试后停止工作,而不是崩溃。我想问一下perform方法中的重试次数,所以如果重试次数等于x,我就可以返回。

def perform(args)
  return if retry_count > 5
  ...
end

使用Sidekiq 2.12。

修改

我(不是OP)有同样的问题,但原因不同。如果正在重试作业,我想进行额外的健全性检查以确保需要该作业,并且如果不再期望成功,则退出重试,因为在排队后外部发生了更改。

那么,有没有办法获得当前工作的重试次数?目前的答案只是建议你可以绕过需要它的方法,或者可以从工作之外得到它。

4 个答案:

答案 0 :(得分:13)

这可以通过添加sidekiq中间件来设置msg [' retry_count']作为作业类的实例变量来实现。

添加一个中间件(在Rails中,它通常是/config/initializers/文件夹中的文件),如下所示:

class SidekiqMiddleware
    def call(worker, job, queue)
        worker.retry_count = job['retry_count'] if worker.respond_to?(:retry_count)
        yield
    end
end

Sidekiq.configure_server do |config|
    config.server_middleware do |chain|
        chain.add SidekiqMiddleware
    end
end

在你的工作中:

include Sidekiq::Worker
attr_accessor :retry_count

def retry_count
  @retry_count || 0
end

def perform(args)
  return if retry_count > 5
  ...
end

答案 1 :(得分:7)

你不需要直接处理这个逻辑来完成你想要的。简单地为你的工人添加一些配置。注意sidekiq_options。根据您在下面的评论"防止Sidekiq将作业移动到死亡作业队列"

 class MyWorker  
     include Sidekiq::Worker
     sidekiq_options :retry => 5, :dead => false

      def perform
          #do some stuff
      end
 end

那么这份工作应该只重试5次并且优雅地失败。此外,如果您想在执行5次重试后执行代码块,则该工作程序有一个名为sidekiq_retries_exhausted的方法,您可以在其中执行一些自定义日志记录等。

答案 2 :(得分:2)

您可以使用Sidekiq API访问重试:

https://github.com/mperham/sidekiq/wiki/API#retries

找到您需要的工作,并使用job['retry_count']获取重试次数。

答案 3 :(得分:0)

我的用例是避免在部署期间发生异常/停机时安排多个作业。为此,我需要 retry_count。以上解决方案不适用于 sidekiq ~> 5.0.4,这是我测试过的解决方案

# config/initializers/sidekiq.rb

# define your middleware
module Sidekiq::Middleware::Server
  class SetRetryCountMiddleware
    def call(worker, job_params, _queue)
      retry_count = job_params["retry_count"]
      worker.instance_variable_set(:@retry_count, retry_count)
      yield
    end
  end
end

# add your defined middleware
Sidekiq.configure_server do |config|
  config.server_middleware do |chain|
    chain.add Sidekiq::Middleware::Server::SetRetryCountMiddleware
  end
  config.redis = {url: "redis://sidekiq:6379/0"}
  config.logger.level = Logger::INFO
end

& 在你的工作人员中

class YetAnotherWorker < Base
  sidekiq_options  :queue => :critical, :retry => true

  def perform(args)
    begin
      # lines that might result in exception
    rescue => exception
      logger.warn("#{exception.class}")
      raise(exception)
    ensure
      # below line will ensure job is scheduled only once, avoiding multiple jobs if above lines throws an error
      schedule_next_run({my_key: "my_value"})
    end
  end

  def schedule_next_run(args)
    YetAnotherWorker.perform_at(Time.now + 7.days, args) if first_run
  end

  def first_run
    @retry_count.nil?
  end

end

而且 retry_count 键在第一次运行时在 job_params 中不可用,因此计数看起来像 nil,0,1,2..