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
ただし、Sidekiqなどの再試行回数を設定する場合:
include Sidekiq::Worker
sidekiq_options :retry => 5
このサンプルコードで行う方法
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 }
しかし、あまり良くないようです。
また、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 から取得します。
できません。 Sidekiq固有のものを使用する場合は、Sidekiq固有のAPIを使用する必要があります。 ActiveJobはSidekiqの再試行メカニズムを公開していません。
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 で説明されているように、一定の待機間隔または指数待機戦略を設定することもできます。
こちら Sidekiqのデフォルトを参照してください。属性retry
は、想定した数値ではなくブール値を「受け入れ」ます。
Active_jobのRails this other file )へのマージから、もう一度retry
が再試行回数を受け入れないことがわかります。
ドキュメントの説明 では、ジョブが再試行するかどうかをジョブごとに定義できます。
また、config/sidekiq.yml
ファイルはこの番号を受信できますが、受信できないようです。
最後に、
25回の再試行(約21日)以内にバグを修正しないと、Sidekiqは再試行を停止し、ジョブをDead Job Queueに移動します。バグを修正し、Web UIを使用して、今後6か月以内であればいつでも手動でジョブを再試行できます。
仕事をする 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
ちなみに、この問題はSidekiq 6.0のリリースで修正されています。ここで変更ログを確認できます: https://github.com/mperham/sidekiq/blob/master/Changes.md
ただし、基本的には、オプションハッシュを使用してsidekiq_options
を呼び出すことにより、同じオプションを渡すことができます。マイク・パーハムに感謝します。