概要
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
長いので jid
と retry_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 件のコメント:
コメントを投稿