solid_queue_tui 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/exe/sqtui +20 -1
  3. data/lib/solid_queue_tui/actions/discard_job.rb +4 -21
  4. data/lib/solid_queue_tui/actions/discard_scheduled_job.rb +5 -21
  5. data/lib/solid_queue_tui/actions/dispatch_scheduled_job.rb +4 -23
  6. data/lib/solid_queue_tui/actions/enqueue_recurring_task.rb +12 -0
  7. data/lib/solid_queue_tui/actions/retry_job.rb +14 -59
  8. data/lib/solid_queue_tui/actions/toggle_queue_pause.rb +19 -0
  9. data/lib/solid_queue_tui/application.rb +73 -17
  10. data/lib/solid_queue_tui/cli.rb +15 -8
  11. data/lib/solid_queue_tui/components/header.rb +26 -27
  12. data/lib/solid_queue_tui/components/help_bar.rb +1 -0
  13. data/lib/solid_queue_tui/components/job_table.rb +14 -2
  14. data/lib/solid_queue_tui/data/failed_query.rb +37 -91
  15. data/lib/solid_queue_tui/data/jobs_query.rb +90 -123
  16. data/lib/solid_queue_tui/data/processes_query.rb +10 -34
  17. data/lib/solid_queue_tui/data/queues_query.rb +6 -15
  18. data/lib/solid_queue_tui/data/recurring_tasks_query.rb +36 -0
  19. data/lib/solid_queue_tui/data/stats.rb +9 -27
  20. data/lib/solid_queue_tui/railtie.rb +9 -0
  21. data/lib/solid_queue_tui/version.rb +1 -1
  22. data/lib/solid_queue_tui/views/blocked_view.rb +126 -46
  23. data/lib/solid_queue_tui/views/concerns/filterable.rb +128 -0
  24. data/lib/solid_queue_tui/views/dashboard_view.rb +2 -1
  25. data/lib/solid_queue_tui/views/failed_view.rb +62 -72
  26. data/lib/solid_queue_tui/views/finished_view.rb +54 -67
  27. data/lib/solid_queue_tui/views/in_progress_view.rb +124 -44
  28. data/lib/solid_queue_tui/views/queues_view.rb +119 -35
  29. data/lib/solid_queue_tui/views/recurring_tasks_view.rb +202 -0
  30. data/lib/solid_queue_tui/views/scheduled_view.rb +74 -8
  31. data/lib/solid_queue_tui.rb +15 -4
  32. data/lib/tasks/solid_queue_tui.rake +8 -0
  33. metadata +16 -24
  34. data/lib/solid_queue_tui/connection.rb +0 -58
@@ -10,109 +10,55 @@ module SolidQueueTui
10
10
  keyword_init: true
11
11
  )
12
12
 
13
- def self.fetch(filter: nil, limit: 200)
14
- conn = ActiveRecord::Base.connection
13
+ def self.fetch(filter: nil, queue: nil, limit: 100, offset: 0)
14
+ scope = SolidQueue::FailedExecution.joins(:job).includes(:job)
15
+ scope = scope.merge(SolidQueue::Job.where("class_name LIKE ?", "%#{filter}%")) if filter.present?
16
+ scope = scope.merge(SolidQueue::Job.where(queue_name: queue)) if queue.present?
17
+ scope = scope.order(created_at: :desc).offset(offset).limit(limit)
15
18
 
16
- sql = <<~SQL
17
- SELECT
18
- fe.id,
19
- fe.job_id,
20
- j.queue_name,
21
- j.class_name,
22
- j.priority,
23
- j.active_job_id,
24
- j.arguments,
25
- j.created_at AS job_created_at,
26
- fe.error,
27
- fe.created_at AS failed_at
28
- FROM solid_queue_failed_executions fe
29
- JOIN solid_queue_jobs j ON j.id = fe.job_id
30
- SQL
31
-
32
- if filter && !filter.empty?
33
- sql += " WHERE j.class_name LIKE #{conn.quote("%#{filter}%")}"
34
- end
35
-
36
- sql += " ORDER BY fe.created_at DESC LIMIT #{limit.to_i}"
37
-
38
- rows = conn.select_all(sql)
39
- rows.map do |row|
40
- error = parse_json(row["error"])
41
-
42
- FailedJob.new(
43
- id: row["id"].to_i,
44
- job_id: row["job_id"].to_i,
45
- queue_name: row["queue_name"],
46
- class_name: row["class_name"],
47
- priority: row["priority"].to_i,
48
- error_class: error["exception_class"] || error["class"] || "Unknown",
49
- error_message: error["message"] || "No message",
50
- backtrace: error["backtrace"] || [],
51
- active_job_id: row["active_job_id"],
52
- arguments: parse_json(row["arguments"]),
53
- failed_at: parse_time(row["failed_at"]),
54
- created_at: parse_time(row["job_created_at"])
55
- )
56
- end
19
+ scope.map { |fe| build_failed_job(fe) }
57
20
  rescue => e
21
+ Rails.logger.tagged("SQTUI") { Rails.logger.error("FailedQuery.fetch error: #{e.class}: #{e.message}") } if defined?(Rails) && Rails.logger
58
22
  []
59
23
  end
60
24
 
61
- def self.fetch_one(id)
62
- conn = ActiveRecord::Base.connection
63
-
64
- row = conn.select_one(<<~SQL)
65
- SELECT
66
- fe.id,
67
- fe.job_id,
68
- j.queue_name,
69
- j.class_name,
70
- j.priority,
71
- j.active_job_id,
72
- j.arguments,
73
- j.created_at AS job_created_at,
74
- fe.error,
75
- fe.created_at AS failed_at
76
- FROM solid_queue_failed_executions fe
77
- JOIN solid_queue_jobs j ON j.id = fe.job_id
78
- WHERE fe.id = #{conn.quote(id.to_i)}
79
- SQL
80
-
81
- return nil unless row
25
+ def self.count(filter: nil, queue: nil)
26
+ scope = SolidQueue::FailedExecution.joins(:job)
27
+ scope = scope.merge(SolidQueue::Job.where("class_name LIKE ?", "%#{filter}%")) if filter.present?
28
+ scope = scope.merge(SolidQueue::Job.where(queue_name: queue)) if queue.present?
29
+ scope.count
30
+ rescue => e
31
+ Rails.logger.tagged("SQTUI") { Rails.logger.error("FailedQuery.count error: #{e.class}: #{e.message}") } if defined?(Rails) && Rails.logger
32
+ 0
33
+ end
82
34
 
83
- error = parse_json(row["error"])
35
+ def self.fetch_one(id)
36
+ fe = SolidQueue::FailedExecution.includes(:job).find_by(id: id)
37
+ return nil unless fe
84
38
 
85
- FailedJob.new(
86
- id: row["id"].to_i,
87
- job_id: row["job_id"].to_i,
88
- queue_name: row["queue_name"],
89
- class_name: row["class_name"],
90
- priority: row["priority"].to_i,
91
- error_class: error["exception_class"] || error["class"] || "Unknown",
92
- error_message: error["message"] || "No message",
93
- backtrace: error["backtrace"] || [],
94
- active_job_id: row["active_job_id"],
95
- arguments: parse_json(row["arguments"]),
96
- failed_at: parse_time(row["failed_at"]),
97
- created_at: parse_time(row["job_created_at"])
98
- )
39
+ build_failed_job(fe)
99
40
  rescue => e
100
41
  nil
101
42
  end
102
43
 
103
- private_class_method def self.parse_json(value)
104
- return {} if value.nil?
105
- value.is_a?(Hash) || value.is_a?(Array) ? value : JSON.parse(value.to_s)
106
- rescue JSON::ParserError
107
- {}
108
- end
109
-
110
- private_class_method def self.parse_time(value)
111
- return nil if value.nil?
112
- value.is_a?(Time) ? value : Time.parse(value.to_s)
113
- rescue
114
- nil
44
+ def self.build_failed_job(fe)
45
+ job = fe.job
46
+ FailedJob.new(
47
+ id: fe.id,
48
+ job_id: job.id,
49
+ queue_name: job.queue_name,
50
+ class_name: job.class_name,
51
+ priority: job.priority,
52
+ error_class: fe.exception_class || "Unknown",
53
+ error_message: fe.message || "No message",
54
+ backtrace: fe.backtrace || [],
55
+ active_job_id: job.active_job_id,
56
+ arguments: job.arguments,
57
+ failed_at: fe.created_at,
58
+ created_at: job.created_at
59
+ )
115
60
  end
61
+ private_class_method :build_failed_job
116
62
  end
117
63
  end
118
64
  end
@@ -11,167 +11,134 @@ module SolidQueueTui
11
11
  keyword_init: true
12
12
  )
13
13
 
14
- def self.fetch(status:, filter: nil, queue: nil, limit: 200)
14
+ def self.fetch(status:, filter: nil, queue: nil, limit: 100, offset: 0)
15
15
  case status
16
- when "claimed" then fetch_claimed(filter: filter, queue: queue, limit: limit)
17
- when "blocked" then fetch_blocked(filter: filter, queue: queue, limit: limit)
18
- when "scheduled" then fetch_scheduled(filter: filter, queue: queue, limit: limit)
19
- when "completed" then fetch_finished(filter: filter, queue: queue, limit: limit)
16
+ when "claimed" then fetch_claimed(filter: filter, queue: queue, limit: limit, offset: offset)
17
+ when "blocked" then fetch_blocked(filter: filter, queue: queue, limit: limit, offset: offset)
18
+ when "scheduled" then fetch_scheduled(filter: filter, queue: queue, limit: limit, offset: offset)
19
+ when "completed" then fetch_finished(filter: filter, queue: queue, limit: limit, offset: offset)
20
20
  else []
21
21
  end
22
22
  rescue => e
23
23
  []
24
24
  end
25
25
 
26
- def self.fetch_claimed(filter: nil, queue: nil, limit: 200)
27
- conn = ActiveRecord::Base.connection
28
-
29
- sql = <<~SQL
30
- SELECT
31
- j.id, j.queue_name, j.class_name, j.priority,
32
- j.active_job_id, j.concurrency_key, j.created_at,
33
- ce.process_id AS worker_id,
34
- ce.created_at AS started_at
35
- FROM solid_queue_claimed_executions ce
36
- JOIN solid_queue_jobs j ON j.id = ce.job_id
37
- SQL
38
-
39
- conditions = []
40
- conditions << "j.queue_name = #{conn.quote(queue)}" if queue
41
- conditions << "j.class_name LIKE #{conn.quote("%#{filter}%")}" if filter && !filter.empty?
26
+ def self.count(status:, filter: nil, queue: nil)
27
+ case status
28
+ when "claimed" then count_scope(SolidQueue::ClaimedExecution.joins(:job), filter: filter, queue: queue)
29
+ when "blocked" then count_scope(SolidQueue::BlockedExecution.joins(:job), filter: filter, queue: queue)
30
+ when "scheduled" then count_scope(SolidQueue::ScheduledExecution.joins(:job), filter: filter, queue: queue)
31
+ when "completed" then count_finished(filter: filter, queue: queue)
32
+ else 0
33
+ end
34
+ rescue => e
35
+ 0
36
+ end
42
37
 
43
- sql += " WHERE #{conditions.join(' AND ')}" unless conditions.empty?
44
- sql += " ORDER BY ce.job_id ASC LIMIT #{limit.to_i}"
38
+ def self.fetch_claimed(filter: nil, queue: nil, limit: 100, offset: 0)
39
+ scope = SolidQueue::ClaimedExecution.joins(:job)
40
+ scope = scope.merge(SolidQueue::Job.where(queue_name: queue)) if queue
41
+ scope = apply_class_name_filter(scope, filter)
42
+ scope = scope.order(job_id: :asc).offset(offset).limit(limit)
45
43
 
46
- conn.select_all(sql).map do |row|
44
+ scope.includes(:job).map do |ce|
45
+ job = ce.job
47
46
  Job.new(
48
- id: row["id"].to_i,
49
- queue_name: row["queue_name"],
50
- class_name: row["class_name"],
51
- priority: row["priority"].to_i,
47
+ id: job.id,
48
+ queue_name: job.queue_name,
49
+ class_name: job.class_name,
50
+ priority: job.priority,
52
51
  status: "claimed",
53
- active_job_id: row["active_job_id"],
54
- concurrency_key: row["concurrency_key"],
55
- created_at: parse_time(row["created_at"]),
56
- worker_id: row["worker_id"]&.to_i,
57
- started_at: parse_time(row["started_at"])
52
+ active_job_id: job.active_job_id,
53
+ concurrency_key: job.concurrency_key,
54
+ created_at: job.created_at,
55
+ worker_id: ce.process_id,
56
+ started_at: ce.created_at
58
57
  )
59
58
  end
60
59
  end
61
60
 
62
- def self.fetch_blocked(filter: nil, queue: nil, limit: 200)
63
- conn = ActiveRecord::Base.connection
64
-
65
- sql = <<~SQL
66
- SELECT
67
- j.id, j.queue_name, j.class_name, j.priority,
68
- j.active_job_id, j.concurrency_key, j.created_at,
69
- be.expires_at,
70
- be.created_at AS blocked_since
71
- FROM solid_queue_blocked_executions be
72
- JOIN solid_queue_jobs j ON j.id = be.job_id
73
- SQL
74
-
75
- conditions = []
76
- conditions << "j.queue_name = #{conn.quote(queue)}" if queue
77
- conditions << "j.class_name LIKE #{conn.quote("%#{filter}%")}" if filter && !filter.empty?
61
+ def self.fetch_blocked(filter: nil, queue: nil, limit: 100, offset: 0)
62
+ scope = SolidQueue::BlockedExecution.joins(:job)
63
+ scope = scope.merge(SolidQueue::Job.where(queue_name: queue)) if queue
64
+ scope = apply_class_name_filter(scope, filter)
65
+ scope = scope.order(job_id: :asc).offset(offset).limit(limit)
78
66
 
79
- sql += " WHERE #{conditions.join(' AND ')}" unless conditions.empty?
80
- sql += " ORDER BY be.job_id ASC LIMIT #{limit.to_i}"
81
-
82
- conn.select_all(sql).map do |row|
67
+ scope.includes(:job).map do |be|
68
+ job = be.job
83
69
  Job.new(
84
- id: row["id"].to_i,
85
- queue_name: row["queue_name"],
86
- class_name: row["class_name"],
87
- priority: row["priority"].to_i,
70
+ id: job.id,
71
+ queue_name: job.queue_name,
72
+ class_name: job.class_name,
73
+ priority: job.priority,
88
74
  status: "blocked",
89
- active_job_id: row["active_job_id"],
90
- concurrency_key: row["concurrency_key"],
91
- created_at: parse_time(row["blocked_since"]),
92
- expires_at: parse_time(row["expires_at"])
75
+ active_job_id: job.active_job_id,
76
+ concurrency_key: job.concurrency_key,
77
+ created_at: be.created_at,
78
+ expires_at: be.expires_at
93
79
  )
94
80
  end
95
81
  end
96
82
 
97
- # Scheduled: query from scheduled_executions JOIN jobs
98
- def self.fetch_scheduled(filter: nil, queue: nil, limit: 200)
99
- conn = ActiveRecord::Base.connection
100
-
101
- sql = <<~SQL
102
- SELECT
103
- j.id, j.queue_name, j.class_name, j.priority,
104
- j.active_job_id, j.arguments, j.created_at,
105
- se.scheduled_at
106
- FROM solid_queue_scheduled_executions se
107
- JOIN solid_queue_jobs j ON j.id = se.job_id
108
- SQL
109
-
110
- conditions = []
111
- conditions << "j.queue_name = #{conn.quote(queue)}" if queue
112
- conditions << "j.class_name LIKE #{conn.quote("%#{filter}%")}" if filter && !filter.empty?
113
-
114
- sql += " WHERE #{conditions.join(' AND ')}" unless conditions.empty?
115
- sql += " ORDER BY se.scheduled_at ASC, se.priority ASC LIMIT #{limit.to_i}"
83
+ def self.fetch_scheduled(filter: nil, queue: nil, limit: 100, offset: 0)
84
+ scope = SolidQueue::ScheduledExecution.joins(:job)
85
+ scope = scope.merge(SolidQueue::Job.where(queue_name: queue)) if queue
86
+ scope = apply_class_name_filter(scope, filter)
87
+ scope = scope.order(scheduled_at: :asc, priority: :asc).offset(offset).limit(limit)
116
88
 
117
- conn.select_all(sql).map do |row|
89
+ scope.includes(:job).map do |se|
90
+ job = se.job
118
91
  Job.new(
119
- id: row["id"].to_i,
120
- queue_name: row["queue_name"],
121
- class_name: row["class_name"],
122
- priority: row["priority"].to_i,
92
+ id: job.id,
93
+ queue_name: job.queue_name,
94
+ class_name: job.class_name,
95
+ priority: job.priority,
123
96
  status: "scheduled",
124
- active_job_id: row["active_job_id"],
125
- arguments: parse_json(row["arguments"]),
126
- scheduled_at: parse_time(row["scheduled_at"]),
127
- created_at: parse_time(row["created_at"])
97
+ active_job_id: job.active_job_id,
98
+ arguments: job.arguments,
99
+ scheduled_at: se.scheduled_at,
100
+ created_at: job.created_at
128
101
  )
129
102
  end
130
103
  end
131
104
 
132
- # Finished: query from jobs WHERE finished_at IS NOT NULL
133
- def self.fetch_finished(filter: nil, queue: nil, limit: 200)
134
- conn = ActiveRecord::Base.connection
105
+ def self.fetch_finished(filter: nil, queue: nil, limit: 100, offset: 0)
106
+ scope = SolidQueue::Job.finished
107
+ scope = scope.where(queue_name: queue) if queue
108
+ scope = scope.where("class_name LIKE ?", "%#{filter}%") if filter.present?
109
+ scope = scope.order(finished_at: :desc).offset(offset).limit(limit)
135
110
 
136
- sql = <<~SQL
137
- SELECT
138
- j.id, j.queue_name, j.class_name, j.priority,
139
- j.active_job_id, j.arguments, j.finished_at, j.created_at
140
- FROM solid_queue_jobs j
141
- WHERE j.finished_at IS NOT NULL
142
- SQL
143
-
144
- sql += " AND j.queue_name = #{conn.quote(queue)}" if queue
145
- sql += " AND j.class_name LIKE #{conn.quote("%#{filter}%")}" if filter && !filter.empty?
146
- sql += " ORDER BY j.finished_at DESC LIMIT #{limit.to_i}"
147
-
148
- conn.select_all(sql).map do |row|
111
+ scope.map do |job|
149
112
  Job.new(
150
- id: row["id"].to_i,
151
- queue_name: row["queue_name"],
152
- class_name: row["class_name"],
153
- priority: row["priority"].to_i,
113
+ id: job.id,
114
+ queue_name: job.queue_name,
115
+ class_name: job.class_name,
116
+ priority: job.priority,
154
117
  status: "completed",
155
- active_job_id: row["active_job_id"],
156
- arguments: parse_json(row["arguments"]),
157
- finished_at: parse_time(row["finished_at"]),
158
- created_at: parse_time(row["created_at"])
118
+ active_job_id: job.active_job_id,
119
+ arguments: job.arguments,
120
+ finished_at: job.finished_at,
121
+ created_at: job.created_at
159
122
  )
160
123
  end
161
124
  end
162
125
 
163
- private_class_method def self.parse_time(value)
164
- return nil if value.nil?
165
- value.is_a?(Time) ? value : Time.parse(value.to_s)
166
- rescue
167
- nil
126
+ private_class_method def self.apply_class_name_filter(scope, filter)
127
+ return scope if filter.blank?
128
+ scope.merge(SolidQueue::Job.where("class_name LIKE ?", "%#{filter}%"))
129
+ end
130
+
131
+ private_class_method def self.count_scope(scope, filter: nil, queue: nil)
132
+ scope = scope.merge(SolidQueue::Job.where(queue_name: queue)) if queue
133
+ scope = apply_class_name_filter(scope, filter)
134
+ scope.count
168
135
  end
169
136
 
170
- private_class_method def self.parse_json(value)
171
- return nil if value.nil?
172
- value.is_a?(String) ? JSON.parse(value) : value
173
- rescue
174
- nil
137
+ private_class_method def self.count_finished(filter: nil, queue: nil)
138
+ scope = SolidQueue::Job.finished
139
+ scope = scope.where(queue_name: queue) if queue
140
+ scope = scope.where("class_name LIKE ?", "%#{filter}%") if filter.present?
141
+ scope.count
175
142
  end
176
143
  end
177
144
  end
@@ -30,46 +30,22 @@ module SolidQueueTui
30
30
  end
31
31
 
32
32
  def self.fetch
33
- conn = ActiveRecord::Base.connection
34
-
35
- rows = conn.select_all(
36
- "SELECT id, kind, pid, hostname, name, last_heartbeat_at, " \
37
- "supervisor_id, metadata, created_at " \
38
- "FROM solid_queue_processes WHERE kind = 'Worker' ORDER BY id"
39
- )
40
-
41
- rows.map do |row|
42
- metadata = parse_json(row["metadata"])
43
-
33
+ SolidQueue::Process.where(kind: "Worker").order(:id).map do |proc|
44
34
  Process.new(
45
- id: row["id"].to_i,
46
- kind: row["kind"],
47
- pid: row["pid"].to_i,
48
- hostname: row["hostname"],
49
- name: row["name"],
50
- last_heartbeat_at: parse_time(row["last_heartbeat_at"]),
51
- supervisor_id: row["supervisor_id"]&.to_i,
52
- metadata: metadata,
53
- created_at: parse_time(row["created_at"])
35
+ id: proc.id,
36
+ kind: proc.kind,
37
+ pid: proc.pid,
38
+ hostname: proc.hostname,
39
+ name: proc.name,
40
+ last_heartbeat_at: proc.last_heartbeat_at,
41
+ supervisor_id: proc.supervisor_id,
42
+ metadata: proc.metadata,
43
+ created_at: proc.created_at
54
44
  )
55
45
  end
56
46
  rescue => e
57
47
  []
58
48
  end
59
-
60
- private_class_method def self.parse_json(value)
61
- return {} if value.nil?
62
- value.is_a?(Hash) ? value : JSON.parse(value.to_s)
63
- rescue JSON::ParserError
64
- {}
65
- end
66
-
67
- private_class_method def self.parse_time(value)
68
- return nil if value.nil?
69
- value.is_a?(Time) ? value : Time.parse(value.to_s)
70
- rescue
71
- nil
72
- end
73
49
  end
74
50
  end
75
51
  end
@@ -9,23 +9,14 @@ module SolidQueueTui
9
9
  )
10
10
 
11
11
  def self.fetch
12
- conn = ActiveRecord::Base.connection
12
+ queues = SolidQueue::Queue.all
13
+ pauses = SolidQueue::Pause.where(queue_name: queues.map(&:name)).index_by(&:queue_name)
13
14
 
14
- queue_sizes = conn.select_rows(
15
- "SELECT queue_name, COUNT(*) FROM solid_queue_ready_executions GROUP BY queue_name ORDER BY queue_name"
16
- ).to_h { |name, count| [name, count.to_i] }
17
-
18
- all_queues = conn.select_values(
19
- "SELECT DISTINCT queue_name FROM solid_queue_jobs WHERE queue_name IS NOT NULL ORDER BY queue_name"
20
- )
21
-
22
- paused = conn.select_values("SELECT queue_name FROM solid_queue_pauses")
23
-
24
- all_queues.map do |name|
15
+ queues.map do |queue|
25
16
  QueueInfo.new(
26
- name: name,
27
- size: queue_sizes[name] || 0,
28
- paused: paused.include?(name)
17
+ name: queue.name,
18
+ size: queue.size,
19
+ paused: pauses[queue.name].present?
29
20
  )
30
21
  end
31
22
  rescue => e
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueueTui
4
+ module Data
5
+ class RecurringTasksQuery
6
+ Task = Struct.new(
7
+ :key, :class_name, :command, :schedule, :queue_name,
8
+ :priority, :last_enqueued_at, :next_time,
9
+ keyword_init: true
10
+ )
11
+
12
+ def self.fetch
13
+ tasks = SolidQueue::RecurringTask.all.to_a
14
+ return [] if tasks.empty?
15
+
16
+ last_enqueued = SolidQueue::RecurringExecution
17
+ .where(task_key: tasks.map(&:key))
18
+ .group(:task_key)
19
+ .maximum(:run_at)
20
+
21
+ tasks.map do |task|
22
+ Task.new(
23
+ key: task.key,
24
+ class_name: task.class_name,
25
+ command: task.command,
26
+ schedule: task.schedule,
27
+ queue_name: task.queue_name,
28
+ priority: task.priority,
29
+ last_enqueued_at: last_enqueued[task.key],
30
+ next_time: task.next_time
31
+ )
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -20,18 +20,16 @@ module SolidQueueTui
20
20
  end
21
21
 
22
22
  def self.fetch
23
- conn = ActiveRecord::Base.connection
24
-
25
23
  new(
26
- ready: count_table(conn, "solid_queue_ready_executions"),
27
- claimed: count_table(conn, "solid_queue_claimed_executions"),
28
- failed: count_table(conn, "solid_queue_failed_executions"),
29
- scheduled: count_table(conn, "solid_queue_scheduled_executions"),
30
- blocked: count_table(conn, "solid_queue_blocked_executions"),
31
- total_jobs: count_table(conn, "solid_queue_jobs"),
32
- completed_jobs: count_where(conn, "solid_queue_jobs", "finished_at IS NOT NULL"),
33
- process_count: count_table(conn, "solid_queue_processes"),
34
- processes_by_kind: processes_by_kind(conn)
24
+ ready: SolidQueue::ReadyExecution.count,
25
+ claimed: SolidQueue::ClaimedExecution.count,
26
+ failed: SolidQueue::FailedExecution.count,
27
+ scheduled: SolidQueue::ScheduledExecution.count,
28
+ blocked: SolidQueue::BlockedExecution.count,
29
+ total_jobs: SolidQueue::Job.count,
30
+ completed_jobs: SolidQueue::Job.finished.count,
31
+ process_count: SolidQueue::Process.count,
32
+ processes_by_kind: SolidQueue::Process.group(:kind).count
35
33
  )
36
34
  rescue => e
37
35
  empty(error: e.message)
@@ -44,22 +42,6 @@ module SolidQueueTui
44
42
  processes_by_kind: {}
45
43
  )
46
44
  end
47
-
48
- private_class_method def self.count_table(conn, table)
49
- conn.select_value("SELECT COUNT(*) FROM #{table}").to_i
50
- end
51
-
52
- private_class_method def self.count_where(conn, table, condition)
53
- conn.select_value("SELECT COUNT(*) FROM #{table} WHERE #{condition}").to_i
54
- end
55
-
56
- private_class_method def self.processes_by_kind(conn)
57
- rows = conn.select_rows(
58
- "SELECT kind, COUNT(*) FROM solid_queue_processes GROUP BY kind"
59
- )
60
- rows.to_h { |kind, count| [kind, count.to_i] }
61
- end
62
-
63
45
  end
64
46
  end
65
47
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueueTui
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ load "tasks/solid_queue_tui.rake"
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidQueueTui
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end