自分用メモ
ActiveJob経由か、直接使うかは
以下の記事で詳細を書いた。
thoames.hatenadiary.jp
自分の場合は、フルにSidekiqの機能を使用したかったため
「直接Sidekiqを使用する」方法を取る。
インストール
Gemfile
gem 'sidekiq' gem 'redis-namespace'
[注意] Redisの設定にnamespaceを設定している場合、
'redis-namespace'のgemをインストールしていいないと、
以下のエラーが出る。
ERROR: Your Redis configuration uses the namespace 'xxxxxxxxx' but the redis-namespace gem is not included in the Gemfile. Add the gem to your Gemfile to continue using a namespace. Otherwise, remove the namespace parameter.
実行
設定ファイルを読み込んで起動する場合
$ bundle exec sidekiq -C config/sidekiq.yml
ベストプラクティス
以下のようにオブジェクトを渡した後、キューが実行される前に
そのオブジェクトが変わった場合、
意図したものと違う内容が実行されてしまう可能性がある。
またRedisにデータを保存する時、引数の情報がJSONとして保存される。
(内部ではRedisに保存するときに、JSON.dumpを使用し、
Redisからデータを参照するときにJSON.loadを使用している)
このため、perform_asyncに渡す引数は必ずJSONとして保存できる
「string, integer, float, boolean, null, array and hash」のいずれかでなければならない。
シンボルやオブジェクト(dateやtimeなども)は引数にしてはいけない。
そのため、処理を特定できる識別子(IDなど)を引数として設定し、
キュー処理の内部で、IDを用い処理を行うことが推奨されている。
✕: 悪い例
quote = Quote.find(quote_id) SomeWorker.perform_async(quote)
○: 良い例
SomeWorker.perform_async(quote_id)
リトライ
例外を発生させれば、自動的にリトライが走る。
class HogeJob < ActiveJob::Base queue_as :default def perform(hoge_id:) raise "error" # 明示的に例外投げる end end
リトライさせたくない場合の設定方法は2種類がある。
① retry: 0
② retry: false
設定例)
... sidekiq_options queue: :xxx, retry: 0 # または sidekiq_options queue: :xxx, retry: false ...
違いは①の場合は、例外が発生した場合、Sidekiq画面の死亡タブで
内容を確認でき手動で再試行が可能だが、②の場合は死亡タブで確認できない。
再試行する必要がなく、死亡したジョブ履歴を追う必要が無い場合を除き
大体の場合、①の方法を選択するほうが良い。
各workerに設定したくない場合はsidekiq.rbに以下のように設定すれば
全体に設定される。
config/initializers/sidekiq.rb
... Sidekiq.default_worker_options = { 'retry' => true } # または Sidekiq.default_worker_options = { 'retry' => 0 } ...
[参考]
Sidekiq で最大回数リトライ後に失敗した場合出すログに例外のバックトレースを含める - Qiita
sidekiqのリトライ回数は26回以上を指定できる - PartyIX
Delayed::Job で絶対にやっておいた方がいいたった1つの設定
sidekiqにretryしてほしくないが、死亡には入って手動retry出来るようにしたい場合
バックトレース
例外発生時に、その例外のbacktraceログも残したい場合は以下の設定を行う。
sidekiq_options backtrace: true
ただし、大量にJOBが失敗するなど、かなりのbacktraceログが発生する可能性がある場合は
Redisに割り当てるメモリを増やすか、backtraceログの出力行を設定する。
出力行は上から数えた行数を設定する。
例)上から20行までを出力する設定
sidekiq_options backtrace: 20
各workerに設定したくない場合はsidekiq.rbに以下のように設定すれば
全体に設定される。
config/initializers/sidekiq.rb
... Sidekiq.default_worker_options = { 'backtrace' => true } # または Sidekiq.default_worker_options = { 'backtrace' => 20 } ...
死亡直前のログ出力
各workerで設定する場合
... include Sidekiq::Worker sidekiq_retries_exhausted do |msg, e| Sidekiq.logger.warn "Failed #{msg['class']} with #{msg['args']}: #{msg['error_message']}" end ...
一括で設定する場合(config/initializers/sidekiq.rb)
Sidekiq.configure_server do |config| config.default_retries_exhausted = -> (job, ex) do Sidekiq.logger.warn "#{job['class']} job is now dead: args(#{job['args']}) => msg(#{job['error_message']})" end end
死亡時にSlack通知
Slack通知にはslack-notifierを使用する。
詳細は以下のページが詳しい。
slack-notifierでrailsからSlackへ簡単にメッセージを送る - Qiita
config.default_retries_exhausted内に設定を追記すれば良い。
config.default_retries_exhausted = -> (job, ex) do message = "#{job['class']} job is now dead: args(#{job['args']}) => msg(#{job['error_message']})" Slack::Notifier.new(Settings[:sidekiq][:slack_notifier_url]).ping(message) Sidekiq.logger.warn message end
ベーシック認証
require 'sidekiq/web' Sidekiq::Web.use Rack::Auth::Basic do |username, password| username == 'basicuser' && password == 'basicpass' end mount Sidekiq::Web => '/sidekiq'
プラグイン
sidekiq-failures
GitHub - mhfs/sidekiq-failures: Keep track of Sidekiq failed jobs
失敗したジョブの詳細をWebUIで見ることができる。
デフォルトだと最新の失敗を、1000個まで確認できる。
以下のヘルパーメソッドは便利そう
Sidekiq::Failures.count Sidekiq::Failures.reset_failures
sidekiq-history
GitHub - russ/sidekiq-history: Sidekiq History
ダッシュボードの拡張。
種類に関係なく全ジョブの履歴ログを見ることができるようになる。
デフォルトだと最新の履歴ログを、1000個まで確認できる。
sidekiq-statistic
GitHub - davydovanton/sidekiq-statistic: See statistic about your workers
ダッシュボードの拡張。
解析用画面がWebUIに追加される。
グラフで成功、失敗したJobの確認ができたり
解析用のAPIが使えるようになる。
sidekiq-unique-jobs
GitHub - mhenrixon/sidekiq-unique-jobs: The missing unique jobs in sidekiq
The job will be unique for the number of seconds configured (default 30 minutes) or until the job has been completed.
Thus, the job will be unique for the shorter of the two.
同じJobが複数登録された場合、それを1つのJobにするっぽい。
デフォルトだと30分。
sidekiq-status
GitHub - utgarda/sidekiq-status: an extension to the sidekiq message processing to track your jobs
進捗率の動的画面表示に仕様。
以下のサイトのようにAjaxで逐一問い合わせる方法もあるが
Railsで非同期処理を実行し、ブラウザで実行結果を取得する - Qiita
以下のサイトのようにActionCableのWebsocketと
組み合わせて使う方法が良いか。
Action Cable でプログレスバーを更新する - Qiita
capistrano-sidekiq
GitHub - seuros/capistrano-sidekiq: Sidekiq integration for Capistrano
capistranoを使用している場合は、デプロイ時に Sidekiq がロードしているコードが更新されないため、
下記の設定を追記して、デプロイと同時に再起動されるように設定します。
config/Capfile
require 'capistrano/sidekiq'
config/deploy.rb
set :sidekiq_role, :web
[参考]
Sidekiqで非業の死を遂げたキューを知る方法 - Qiita
Railsで非同期処理:キュー。Sidekiq(+ActiveJob)がResqueよりも、とても簡単便利。 - Qiita
capistrano-sidekiqを使うのをやめる - Qiita