web-dev-qa-db-ja.com

ActiveJobでSidekiqの再試行回数を設定する方法

Rails APIから、ActiveJobがretry_job間隔を実行できることがわかりました:

my_job_instance.enqueue
my_job_instance.enqueue wait: 5.minutes
my_job_instance.enqueue queue: :important
my_job_instance.enqueue wait_until: Date.tomorrow.midnight

http://api.rubyonrails.org/classes/ActiveJob/Enqueuing.html

ただし、Sidekiqなどの再試行回数を設定する場合:

include Sidekiq::Worker
sidekiq_options :retry => 5

https://github.com/mperham/sidekiq/wiki/Error-Handling

このサンプルコードで行う方法

class SiteScrapperJob < ActiveJob::Base
  rescue_from(ErrorLoadingSite) do
    retry_job queue: :low_priority
  end

  def perform(*args)
    # raise ErrorLoadingSite if cannot scrape
  end
end

これを自分のジョブクラスに追加しました。

Sidekiq.default_worker_options = { retry: 5 }

しかし、あまり良くないようです。

20
scho

また、serializeおよびdeserialize apiを使用して試行回数を保存するこのソリューションに興味があるかもしれません。

class DeliverWebhookJob < ActiveJob::Base
  def serialize
    super.merge('attempt_number' => (@attempt_number || 0) + 1)
  end

  def deserialize(job_data)
    super
    @attempt_number = job_data['attempt_number']
  end

  rescue_from(ErrorLoadingSite) do |exception|
    retry_job(wait: 10) if @attempt_number < 5
  end

  def perform(*args)
    # raise ErrorLoadingSite if cannot scrape
  end
end

here から取得します。

18
Vini Oliveira

できません。 Sidekiq固有のものを使用する場合は、Sidekiq固有のAPIを使用する必要があります。 ActiveJobはSidekiqの再試行メカニズムを公開していません。

13
Mike Perham

Rails 5.1なので、 retry_on メソッドを使用してこれを行う組み込みの方法があります。これは一般的なActiveJobメソッドであるため、任意のキューバックエンドで機能しますが、 Sidekiqだけではありません。

たとえば、次のような特定のジョブを実行できます。

class SiteScraperJob < ActiveJob::Base
  retry_on ErrorLoadingSite, queue: :low_priority, attempts: 5

  def perform(*args)
    # raise ErrorLoadingSite if cannot scrape
  end
end

docs で説明されているように、一定の待機間隔または指数待機戦略を設定することもできます。

11
hattila91

こちら Sidekiqのデフォルトを参照してください。属性retryは、想定した数値ではなくブール値を「受け入れ」ます。

Active_jobのRails this other file )へのマージから、もう一度retryが再試行回数を受け入れないことがわかります。

ドキュメントの説明 では、ジョブが再試行するかどうかをジョブごとに定義できます。

また、config/sidekiq.ymlファイルはこの番号を受信できますが、受信できないようです。

最後に、

25回の再試行(約21日)以内にバグを修正しないと、Sidekiqは再試行を停止し、ジョブをDead Job Queueに移動します。バグを修正し、Web UIを使用して、今後6か月以内であればいつでも手動でジョブを再試行できます。

2
Nuno Costa

仕事をする sidekiq-retry gemがあります

class SiteScrapperJob < ActiveJob::Base
  include ActiveJob::Retry.new(limit: 5, strategy: :exponential)

  def perform(*args)
    # raise ErrorLoadingSite if cannot scrape
  end
end

別のオプションは sidekiqミドルウェア を使用することです:

最初に、サブクラスで使用できるjob_optionsクラスメソッドを定義します。

class ApplicationJob < ActiveJob::Base
  def self.job_options(options)
    @job_options = options
  end

  def self.get_job_options
    @job_options || {}
  end
end

ジョブのクラスからjob_optionsを読み取り、それらをsidekiqのジョブアイテムに書き込むミドルウェアを追加します。

module Sidekiq
 class JobOptionsMiddleware

   def call(job_wrapper, item, queue, redis_pool)
     job = item['args'][0]['job_class'].constantize

     job.get_job_options
       .each{ |option, value| item[option] = value if item[option].nil? }

     yield
   end

 end

 # in sidekiq initializer

 Sidekiq.configure_client do |config|
   config.client_middleware do |chain|
     chain.add Sidekiq::JobOptionsMiddleware
   end
 end

そして最後に

 class SiteScrapperJob < ApplicationJob
   job_options retry: 5

   def perform
     # your code
   end
 end
2
Hirurg103

ちなみに、この問題はSidekiq 6.0のリリースで修正されています。ここで変更ログを確認できます: https://github.com/mperham/sidekiq/blob/master/Changes.md

ただし、基本的には、オプションハッシュを使用してsidekiq_optionsを呼び出すことにより、同じオプションを渡すことができます。マイク・パーハムに感謝します。

1
paascal