sidekiqのリトライ上限を設定して死んだキューをslackで通知する方法


はじめに

非同期でjobを処理してくれるsidekiqを導入する中で、利便性を生かしつつも自分のアプリ専用にカスタマイズしたい、そんな時に役に立った設定をまとめています。

sidekiqとは

sidekiqとは、非同期処理を可能にしてくれるライブラリです。複数のジョブを同時に実行させる時などに、各ジョブのqueueの名称を分けることで、処理の優先順位を指定することができます。似たようなライブラリにresqueやdelayed_jobなどがあるかと思います。
簡単に導入できるのですが、つまづいてしまったキューをデフォルトで25回だか26回だかリトライするとか、その後はDEADとなって実行していたキューのログが見られないなどといった面倒な点もあります。
そこでこの記事では、例外を投げた時などにいつまでもリトライせず上限を設定してDEADとし、その際にslackにキューの内容とエラーメッセージを投げるという設定をする方法についてお話しします。

環境

Ruby 2.6.6
Rails 6.0.2
sidekiqにはredisが必要になります。

# On OSX
brew update
brew install redis
brew services start redis

失敗したキューをダッシュボードで確認する

gemにsidekiq-failuresを追加することでダッシュボードで確認することができ、失敗したキュー全てをリトライさせることもできます。

gem 'sidekiq-failures'

failuresの一覧でもエラーの詳細が確認できます。

他にも投げられたキューを知る&分析するなどでたくさんgemがあるようですので参考までに載せておきます

リトライの上限を設定する

sidekiqは確かデフォルトで25,6回程度リトライをしてからキューを殺すといった仕様になっていたかと思います。
そこで、たくさんのジョブを一気に処理させる時など、そこまでリトライしなくていいからダメになった何度かチャレンジしてダメになったら教えて・・・という人のために、リトライの上限をjobファイルに記載します。

app/jobs/your_job.rb
class YourJob < ActiveJob::Base
  ...
  queue_as :default
  sidekiq_options retry: 5
  ...
end

これで5回トライしてダメだったキューはDEADキューとなります。

キューの死亡をslackで通知

Railsアプリにおいてslack通知をとても簡単にしてくれるgemがslack-incoming-webhooksです。

gem 'slack-incoming-webhooks'

通知させるチャネルのURL取得はこのページを確認してください。

initializerでキューが死亡した場合の処理を設定(チャネルのURLは.envに保存します)

app/config/initializers/sidekiq.rb
Sidekiq.configure_server do |config|
  config.death_handlers << ->(job, ex) do
    slack = Slack::Incoming::Webhooks.new(ENV['SLACK_WEBHOOK_URL'])
    attachments = [{
      title: "Sidekiq failure",
      text: "ONE DEAD JOB IS FOUND:\n (#{job['args']}) \n msg(#{job['error_message']})",
      color: "#fb2489"
    }]
    slack.post "", attachments: attachments
  end
end

これで自然とDEADになってしまったキューはslack通知されるようになります。

注意点

  • sidekiqのダッシュボード上でキューを殺しても通知は来ない
    config.death_handlersに通知の設定をする場合、ダッシュボード上でマニュアルにキューを死亡させた場合には通知が来ません。なのでリトライ上限の5回を超えた場合にのみ通知が来るようになります。

  • rescure_from Exceptionで通知設定するとリトライしてくれない
    例外処理なので一度ジョブを処理してエラーとなると死亡と看做され、slack通知はしてくれますがリトライはしてくれません。なんらかの事情で処理されずそれでもリトライして欲しい場合には、上記の通りconfig.death_handlersでslack通知の設定をおすすめします。