問題
実例をあげます。
試しにデッド状態のジョブをひとつ見てみましょう。
# rails console
Sidekiq::DeadSet.new.to_a.first
=> #<Sidekiq::SortedEntry:0x00007fb9e8788d78
@args=nil,
@item=
{"retry"=>3,
"queue"=>"default",
"class"=>"FooClass",
"args"=>["8ecd1021-62d7-4068-8d7b-bb11033163f6"],
"jid"=>"746d59154e31e75f09109f0b",
"created_at"=>1649321038.4516313,
"enqueued_at"=>1649321184.3722708,
"error_message"=>"undefined method `-' for nil:NilClass",
"error_class"=>"NoMethodError",
"failed_at"=>1649321039.5810795,
"retry_count"=>3,
"retried_at"=>1649321184.4531639},
@parent=#<Sidekiq::DeadSet:0x00007fb9e8712510 @_size=40, @name="dead">,
@queue="default",
@score=1649321184.45449,
@value="(ここは省略します)">
created_at
、enqueued_at
、failed_at
等が日時じゃなくてFloat
型になっていますね
日時を見せてくれ!日時を!
解決策
さっそく解決策です。
Time.at
でTime
オブジェクトに変換すると日時を見ることができます。
Time.at(Sidekiq::DeadSet.new.to_a.first["created_at"])
=> 2022-04-14 04:14:19 +0000
よりよい方法
Time.at
だと協定世界時(UTC)になります。
Time.zone.at
で変換すると日本標準時(JST)になるので、多くのケースではこちらでよいかなと思います。
Time.zone.at(Sidekiq::DeadSet.new.to_a.first["created_at"])
=> Thu, 14 Apr 2022 13:14:19 JST +09:00
解説
では、この数字の正体はいったい何でしょうか?
調べたところどうやら、1970年1月1日午前0時からの経過秒数のようです。
Time オブジェクトは時刻を起算時からの経過秒数で保持しています。起算時は協定世界時(UTC、もしくはその旧称から GMT とも表記されます) の 1970年1月1日午前0時です。
こういうのをエポック秒(UNIX秒)というそうです。
試してみた
# Timeオブジェクトは内部的には起算日からの経過秒数を保持しています。
Time.now.to_i
=> 1652253033
# Time.atを使うと、起算日からの経過秒数をTimeオブジェクトに変換可能
Time.at(1652253033)
=> 2022-05-11 07:10:33 +0000
# 0だとどうなるか見てみましょう
Time.at(0)
=> 1970-01-01 00:00:00 +0000
ちょっと便利なワンライナー
デッド状態のジョブをfailed_at
の昇順で並びかえた上で、failed_at
の一覧を表示します
Sidekiq::DeadSet.new.to_a.sort_by{|job| job["failed_at"] }.map{|job| Time.zone.at(job["failed_at"])}
=> [Thu, 07 Apr 2022 17:42:13 JST +09:00,
Thu, 07 Apr 2022 17:42:16 JST +09:00,
Thu, 07 Apr 2022 17:43:12 JST +09:00,
Thu, 07 Apr 2022 17:43:59 JST +09:00,
Thu, 07 Apr 2022 17:43:59 JST +09:00 ]
failed_at
をenqueued_at
など任意なものに変える