2018年4月14日土曜日

sidekiq/api を使ってキューやジョブの操作をしてみる

概要

Sidekiq はワーカーがエラーをキャッチすると自動でリトライ処理をしてくれます
故にエラーが解消されない限りはワーカーが永遠にジョブを処理し続けてしまいます
そんな場合にはキューからジョブを削除しなければなりません
直接 redis を操作しても問題ないですが Sidekiq にはキューやジョブを操作する API が備わっているので使ってみました

環境

  • macOS 10.13.2
  • Ruby 2.4.1p111
  • Redis 3.2.1
  • sidekiq 5.1.3

Redis に接続する

今回の作業はすべて irb (bundle console) で行います

デフォルトだと localhost:6379 のデータベースインデックス 0 に接続します
今回はインデックスが 1 のデータベースに接続するため切り替える必要があります

irb(main):001:0> require 'sidekiq/api'
=> true
irb(main):002:0> Sidekiq.redis { |con| con.select 1 }
=> "OK"

これでインデックス 1 のデータベースに切り替えできました

キューの一覧を取得する

特にしていしなければ default のみあると思います

irb(main):003:0> Sidekiq::Queue.all
=> [#<Sidekiq::Queue:0x007fc13b3a0238 @name="default", @rname="queue:default">]
irb(main):004:0> q = Sidekiq::Queue.new
=> #<Sidekiq::Queue:0x007fc13b371d20 @name="default", @rname="queue:default">

Sidekiq::Queue.new でキューオブジェクトを作成します
引数に文字列でキュー名を指定することができます
指定しない場合は default になります
今回はこの default キュー内のジョブを削除してみます

キュー内に溜まったジョブの一覧を取得する

each で回すだけです

irb(main):008:0> q.each { |job|
irb(main):009:1* p job
irb(main):010:1> }
=> nil

特に何も入っていないので何も表示されませんでした

リトライ対象のジョブの一覧を取得する

リトライ対象のジョブは別のクラスから取得することができます
Sidekiq::RetrySet を使います

irb(main):014:0> rs = Sidekiq::RetrySet.new
=> #<Sidekiq::RetrySet:0x007fc13b83fc08 @name="retry", @_size=1>
irb(main):015:0> rs.each { |job|
irb(main):016:1* p job['jid']
irb(main):017:1> p job['retry_count']
irb(main):018:1> }
"85d82e45decb7474d5fbfbaf"
6
=> nil

長いので jidretry_count だけ表示しています
ここにジョブが入っていると default キューを見るワーカーがこのジョブを処理し続けます

リトライジョブを削除する

ジョブに対して delete メソッドをコールするだけです

irb(main):022:0> rs.each { |job|
irb(main):023:1* job.delete
irb(main):024:1> }
=> nil
irb(main):025:0> rs.each { |job|
irb(main):026:1* p job.jid
irb(main):027:1> }
=> nil
irb(main):028:0> rs.size
=> 0

もし特定のジョブだけを削除したい場合は一旦 jid のリストを取得して、指定の jid とマッチしたら delete するという感じの処理を追加すれば OK です
おそらくこの操作が一番運用で使うんじゃないかなと思います

最後に

sidekiq/api を使ってキューやジョブの操作をしてみました
前回紹介したダッシュボードの機能を使えば UI でもリトライジョブを削除することができると思います
1 つや 2 つであれば UI でもいいですが、何百何千という単位で処理したい場合はこれを使ってプログラムを組んだほうが良いかなと思います

参考サイト

0 件のコメント:

コメントを投稿