行動すれば次の現実

ほどよくモダンなシステム開発を目指しています。メインテーマは生産性、Ruby、Javascriptです。

Sidekiqでスタータスチェックや進捗管理ができるsidekiq-statusの使い方

Sidekiqのステータスチェックや進捗状況管理に便利なsidekiq-statusの使い方について説明します。

sidekiq-statusとは

sidekiq-statusを使うとジョブのスタータスや進捗状況を簡単に把握することができます。

sidekiq-statusはSidekiqのジョブに関する追跡情報をredis上に保存します。 クライアントからはjob_idを用いて簡単にそれらの情報を取得することができます。

例えば、重たい非同期処理(ジョブ)を画面から実行して、画面上にステータスや進捗情報を表示したい場合などに役立ちます。

sidekiq-statusの導入

sidekiq-statusのインストール

Gemfile

gem 'sidekiq-status'

sidekiq-statusの設定を追加

config/initializers/sidekiq.rb

Sidekiq.configure_server do |config|
  # 下記を追記
  Sidekiq::Status.configure_server_middleware config, expiration: 30.minutes
  Sidekiq::Status.configure_client_middleware config, expiration: 30.minutes
end

Sidekiq.configure_client do |config|
  # 下記を追記
  Sidekiq::Status.configure_client_middleware config, expiration: 30.minutes
end

expirationにはステータスをredisに保持する期間を指定します。デフォルトでは30分です。

expirationはジョブクラスごとに上書きすることも可能です。ジョブの実行時間よりも長い時間を指定する必要があります。

ジョブクラスにSidekiq::Status::Workerをinclude

ステータス管理したいジョブクラスにSidekiq::Status::Workerをincludeすることでステータスを確認することができます。

class SampleJob
  include Sidekiq::Job
  include Sidekiq::Status::Worker # 追記します

  def perform(*args)
  end
end

ジョブステータス用の管理画面を追加

sidekiq-statusではsidekiqの管理画面にスタータス情報を表示する拡張機能を提供しています。

routes.rbに下記の記載をするとstatusesタブが新たに追加されます。

config/routes.rb

require 'sidekiq/web'
require 'sidekiq-status/web' # 追記する

statusesタブ

sidekiq-statusで出来ること

スタータスの把握

Sidekiq::Status::statusを使用することでスタータスを把握することが出来ます。

job_id = SampleJob.perform_async
status = Sidekiq::Status::status(job_id)

# statusは下記のいずれか
# queued,working,retrying,complete,failed,interrupted

# スタータス毎のメソッドも用意されている
Sidekiq::Status::queued? job_id
Sidekiq::Status::working? job_id
Sidekiq::Status::retrying?  job_id
Sidekiq::Status::complete?  job_id
Sidekiq::Status::failed? job_id
Sidekiq::Status::interrupted? job_id

注意点

statusにnilやfalseが返却されることがあります。 これはexpirationを超過している場合や、何らかの理由でSidekiqやredisの情報が消失された場合などに発生します。

この場合、画面上では失敗やエラーとして表現するなどの工夫が必要になります。

進捗管理

以下の様に進捗率を設定したり、自前の状態を保持することが可能です。

class SampleJob
  include Sidekiq::Job
  include Sidekiq::Status::Worker

  def perform(*args)
    total 100 # 進捗率の最大値

    # storeを使うと任意の状態(hoge_statusとする)を保持することができる
    store hoge_status: 'start'
    # retrieveでhoge_statusの状態を取得できる
    progress = retrieve :hoge_status
    p progress

    # 5秒待機(なんらかの処理を想定)
    sleep 5

    # 進捗率を50%に変更
    at 50, 'complete import'
    # hoge_statusの状態をimportedに変更
    store hoge_status: 'imported'

    # 5秒待機(なんらかの処理を想定)
    sleep 5

    # 進捗率を100%に変更
    at 100, 'finish'
    # hoge_statusの状態をfinishに変更
    store hoge_status: 'finish sample'
  end
end

クライアントからステータスを確認するには以下のメソッドを用います。

job_id = SampleJob.perform_async
Sidekiq::Status::get job_id, :hoge_status #=> 'start'
Sidekiq::Status::at job_id #=> 0

# 10秒後
Sidekiq::Status::total job_id #=> 100
Sidekiq::Status::message job_id #=> "finish"
Sidekiq::Status::get job_id, :hoge_status #=> 'finish sample'

管理画面からもステータスや進捗状況が確認できます。

管理画面から見た進捗率