Module: TalkToYourApp::Plugins::Jobs::Adapters::Sidekiq

Defined in:
lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb

Overview

Sidekiq adapter. Reads queue, retry, and dead-set data through Sidekiq’s public API. Read-only: it never enqueues, retries, or kills. All four methods return the common shape defined by Jobs::Interface.

Constant Summary collapse

REQUIRED_GEM =
{ const: "Sidekiq", gem_name: "sidekiq" }.freeze

Class Method Summary collapse

Class Method Details

.failed_jobs(limit:) ⇒ Object



44
45
46
47
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 44

def failed_jobs(limit:)
  load_api
  ::Sidekiq::DeadSet.new.first(limit).map { |entry| job_hash(entry) }
end

.iso8601(unix_timestamp) ⇒ Object

Sidekiq stores timestamps as Unix floats; surface ISO-8601 so the field type matches the Solid Queue adapter.



80
81
82
83
84
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 80

def iso8601(unix_timestamp)
  return nil unless unix_timestamp

  Time.at(unix_timestamp.to_f).utc.iso8601
end

.job_hash(entry) ⇒ Object

Both Sidekiq::JobRecord and Sidekiq::SortedEntry expose the raw job hash via #item. Keys are always present (nil where absent) so the shape is stable across adapters and across recent/failed.



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 66

def job_hash(entry)
  item = entry.respond_to?(:item) ? entry.item : entry
  {
    jid: item["jid"],
    class: item["class"] || item["wrapped"],
    queue: item["queue"],
    args: item["args"],
    enqueued_at: iso8601(item["enqueued_at"] || item["created_at"]),
    error_message: item["error_message"],
  }
end

.load_apiObject

Sidekiq’s metrics API (Stats/Queue/RetrySet/DeadSet) is not loaded by ‘require “sidekiq”`. Load it lazily at call time — never at gem load —so an app without Sidekiq can still load this adapter file. `require` is idempotent, so repeated calls are cheap.



95
96
97
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 95

def load_api
  require "sidekiq/api"
end

.queue_sizesObject



21
22
23
24
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 21

def queue_sizes
  load_api
  ::Sidekiq::Stats.new.queues
end

.rate_metrics(window:) ⇒ Object

Sidekiq exposes cumulative and day-resolution counts, not arbitrary trailing windows; the response says so via ‘note`.



51
52
53
54
55
56
57
58
59
60
61
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 51

def rate_metrics(window:)
  load_api
  stats = ::Sidekiq::Stats.new
  {
    window_seconds: window,
    processed: stats.processed,
    failed: stats.failed,
    enqueued: stats.enqueued,
    note: "Sidekiq reports cumulative processed/failed counts; the window is not applied at sub-day resolution.",
  }
end

.raw_enqueued_at(entry) ⇒ Object



86
87
88
89
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 86

def raw_enqueued_at(entry)
  item = entry.respond_to?(:item) ? entry.item : entry
  (item["enqueued_at"] || item["created_at"] || 0).to_f
end

.recent_jobs(limit:) ⇒ Object

Sidekiq has no first-class “recent jobs” API; we scan the queues and the retry set, sort newest-first by enqueued time, and cap at limit. Per-queue fetch is bounded so a many-queue install does not materialize limit*queue_count records to return ‘limit`; this can miss the very newest jobs when they cluster in one queue, which is acceptable for an inspection tool.



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 32

def recent_jobs(limit:)
  load_api
  queues = ::Sidekiq::Queue.all
  per_queue = [(limit / [queues.size, 1].max) + 1, limit].min
  queued = queues.flat_map { |queue| queue.first(per_queue) }
  retries = ::Sidekiq::RetrySet.new.first(limit)
  (queued + retries)
    .sort_by { |entry| -raw_enqueued_at(entry) }
    .first(limit)
    .map { |entry| job_hash(entry) }
end

.required_gemObject



17
18
19
# File 'lib/talk_to_your_app/plugins/jobs/adapters/sidekiq.rb', line 17

def required_gem
  REQUIRED_GEM
end