solid_queue_tui 0.1.2 → 0.2.0
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.
- checksums.yaml +4 -4
- data/exe/qtop +35 -0
- data/exe/sqtui +19 -2
- data/lib/solid_queue_tui/application.rb +37 -4
- data/lib/solid_queue_tui/cli.rb +2 -2
- data/lib/solid_queue_tui/components/job_table.rb +2 -3
- data/lib/solid_queue_tui/data/hourly_stats_query.rb +85 -0
- data/lib/solid_queue_tui/data/jobs_query.rb +31 -0
- data/lib/solid_queue_tui/data/processes_query.rb +23 -0
- data/lib/solid_queue_tui/data/stats.rb +15 -3
- data/lib/solid_queue_tui/formatting_helpers.rb +63 -0
- data/lib/solid_queue_tui/version.rb +1 -1
- data/lib/solid_queue_tui/views/blocked_view.rb +9 -77
- data/lib/solid_queue_tui/views/concerns/confirmable.rb +53 -0
- data/lib/solid_queue_tui/views/concerns/filterable.rb +4 -0
- data/lib/solid_queue_tui/views/concerns/paginatable.rb +79 -0
- data/lib/solid_queue_tui/views/dashboard_view.rb +228 -22
- data/lib/solid_queue_tui/views/failed_view.rb +49 -152
- data/lib/solid_queue_tui/views/finished_view.rb +12 -80
- data/lib/solid_queue_tui/views/in_progress_view.rb +9 -72
- data/lib/solid_queue_tui/views/job_detail_view.rb +179 -31
- data/lib/solid_queue_tui/views/processes_view.rb +2 -24
- data/lib/solid_queue_tui/views/queues_view.rb +226 -87
- data/lib/solid_queue_tui/views/recurring_tasks_view.rb +22 -69
- data/lib/solid_queue_tui/views/scheduled_view.rb +39 -142
- data/lib/solid_queue_tui.rb +4 -0
- metadata +9 -3
|
@@ -4,62 +4,29 @@ module SolidQueueTui
|
|
|
4
4
|
module Views
|
|
5
5
|
class ScheduledView
|
|
6
6
|
include Filterable
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
include Confirmable
|
|
8
|
+
include Paginatable
|
|
9
|
+
include FormattingHelpers
|
|
10
10
|
|
|
11
11
|
def initialize(tui)
|
|
12
12
|
@tui = tui
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@selected_row = 0
|
|
16
|
-
@jobs = []
|
|
17
|
-
@total_count = nil
|
|
18
|
-
@all_loaded = false
|
|
19
|
-
@confirm_action = nil
|
|
13
|
+
init_pagination
|
|
14
|
+
init_confirm
|
|
20
15
|
init_filter
|
|
21
16
|
end
|
|
22
17
|
|
|
23
18
|
def update(jobs:)
|
|
24
|
-
|
|
25
|
-
@all_loaded = jobs.size < SolidQueueTui.page_size
|
|
26
|
-
@selected_row = @selected_row.clamp(0, [@jobs.size - 1, 0].max)
|
|
27
|
-
@table_state.select(@selected_row)
|
|
19
|
+
update_items(jobs)
|
|
28
20
|
end
|
|
29
21
|
|
|
30
22
|
def append(jobs:)
|
|
31
|
-
|
|
32
|
-
@all_loaded = jobs.size < SolidQueueTui.page_size
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def total_count=(count)
|
|
36
|
-
@total_count = count
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def current_offset
|
|
40
|
-
@jobs.size
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def reset_pagination!
|
|
44
|
-
@jobs = []
|
|
45
|
-
@total_count = nil
|
|
46
|
-
@all_loaded = false
|
|
47
|
-
@selected_row = 0
|
|
48
|
-
@table_state.select(0)
|
|
23
|
+
append_items(jobs)
|
|
49
24
|
end
|
|
50
25
|
|
|
51
26
|
def render(frame, area)
|
|
52
|
-
if
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
direction: :vertical,
|
|
56
|
-
constraints: [
|
|
57
|
-
@tui.constraint_length(3),
|
|
58
|
-
@tui.constraint_fill(1)
|
|
59
|
-
]
|
|
60
|
-
)
|
|
61
|
-
render_confirm(frame, confirm_area)
|
|
62
|
-
render_table(frame, content_area)
|
|
27
|
+
if confirm_mode?
|
|
28
|
+
render_table(frame, area)
|
|
29
|
+
render_confirm_popup(frame, area)
|
|
63
30
|
elsif filter_mode?
|
|
64
31
|
filter_area, content_area = @tui.layout_split(
|
|
65
32
|
area,
|
|
@@ -77,7 +44,7 @@ module SolidQueueTui
|
|
|
77
44
|
end
|
|
78
45
|
|
|
79
46
|
def handle_input(event)
|
|
80
|
-
if
|
|
47
|
+
if confirm_mode?
|
|
81
48
|
handle_confirm_input(event)
|
|
82
49
|
elsif filter_mode?
|
|
83
50
|
handle_filter_input(event)
|
|
@@ -86,21 +53,13 @@ module SolidQueueTui
|
|
|
86
53
|
end
|
|
87
54
|
end
|
|
88
55
|
|
|
89
|
-
def selected_item
|
|
90
|
-
return nil if @jobs.empty? || @selected_row >= @jobs.size
|
|
91
|
-
@jobs[@selected_row]
|
|
92
|
-
end
|
|
93
|
-
|
|
94
56
|
def capturing_input?
|
|
95
|
-
filter_mode? ||
|
|
57
|
+
filter_mode? || confirm_mode?
|
|
96
58
|
end
|
|
97
59
|
|
|
98
60
|
def bindings
|
|
99
|
-
if
|
|
100
|
-
|
|
101
|
-
{ key: "y", action: "Confirm" },
|
|
102
|
-
{ key: "n/Esc", action: "Cancel" }
|
|
103
|
-
]
|
|
61
|
+
if confirm_mode?
|
|
62
|
+
confirm_bindings
|
|
104
63
|
elsif filter_mode?
|
|
105
64
|
filter_bindings
|
|
106
65
|
else
|
|
@@ -108,10 +67,11 @@ module SolidQueueTui
|
|
|
108
67
|
{ key: "j/k", action: "Navigate" },
|
|
109
68
|
{ key: "Enter", action: "Detail" },
|
|
110
69
|
{ key: "/", action: "Filter" },
|
|
70
|
+
clear_filter_binding,
|
|
111
71
|
{ key: "N", action: "Run Now" },
|
|
112
72
|
{ key: "D", action: "Discard" },
|
|
113
73
|
{ key: "G/g", action: "Bottom/Top" }
|
|
114
|
-
]
|
|
74
|
+
].compact
|
|
115
75
|
end
|
|
116
76
|
end
|
|
117
77
|
|
|
@@ -121,10 +81,6 @@ module SolidQueueTui
|
|
|
121
81
|
|
|
122
82
|
private
|
|
123
83
|
|
|
124
|
-
def needs_more?
|
|
125
|
-
!@all_loaded && @selected_row >= @jobs.size - LOAD_THRESHOLD
|
|
126
|
-
end
|
|
127
|
-
|
|
128
84
|
def handle_normal_input(event)
|
|
129
85
|
case event
|
|
130
86
|
in { type: :key, code: "j" } | { type: :key, code: "up" }
|
|
@@ -146,55 +102,37 @@ module SolidQueueTui
|
|
|
146
102
|
in { type: :key, code: "/" }
|
|
147
103
|
enter_filter_mode
|
|
148
104
|
nil
|
|
149
|
-
in { type: :key, code: "
|
|
105
|
+
in { type: :key, code: "c" }
|
|
150
106
|
clear_filter
|
|
151
107
|
else
|
|
152
108
|
nil
|
|
153
109
|
end
|
|
154
110
|
end
|
|
155
111
|
|
|
156
|
-
def
|
|
157
|
-
case
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
return nil unless item
|
|
165
|
-
Actions::DispatchScheduledJob.call(item.id)
|
|
166
|
-
:refresh
|
|
167
|
-
when :discard
|
|
168
|
-
item = selected_item
|
|
169
|
-
return nil unless item
|
|
170
|
-
Actions::DiscardScheduledJob.call(item.id)
|
|
171
|
-
:refresh
|
|
172
|
-
end
|
|
173
|
-
in { type: :key, code: "n" } | { type: :key, code: "esc" }
|
|
174
|
-
@confirm_action = nil
|
|
175
|
-
nil
|
|
176
|
-
else
|
|
177
|
-
nil
|
|
112
|
+
def confirm_message
|
|
113
|
+
case @confirm_action
|
|
114
|
+
when :run_now
|
|
115
|
+
job = selected_item
|
|
116
|
+
"Run job ##{job&.id} (#{job&.class_name}) now? [y/n]"
|
|
117
|
+
when :discard
|
|
118
|
+
job = selected_item
|
|
119
|
+
"Discard job ##{job&.id} (#{job&.class_name})? This cannot be undone. [y/n]"
|
|
178
120
|
end
|
|
179
121
|
end
|
|
180
122
|
|
|
181
|
-
def
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return if @jobs.empty?
|
|
195
|
-
@selected_row = @jobs.size - 1
|
|
196
|
-
@table_state.select(@selected_row)
|
|
197
|
-
return :load_more if needs_more?
|
|
123
|
+
def execute_confirm_action(action)
|
|
124
|
+
case action
|
|
125
|
+
when :run_now
|
|
126
|
+
item = selected_item
|
|
127
|
+
return nil unless item
|
|
128
|
+
Actions::DispatchScheduledJob.call(item.id)
|
|
129
|
+
:refresh
|
|
130
|
+
when :discard
|
|
131
|
+
item = selected_item
|
|
132
|
+
return nil unless item
|
|
133
|
+
Actions::DiscardScheduledJob.call(item.id)
|
|
134
|
+
:refresh
|
|
135
|
+
end
|
|
198
136
|
end
|
|
199
137
|
|
|
200
138
|
def render_table(frame, area)
|
|
@@ -209,7 +147,7 @@ module SolidQueueTui
|
|
|
209
147
|
]
|
|
210
148
|
|
|
211
149
|
now = Time.now.utc
|
|
212
|
-
rows =
|
|
150
|
+
rows = items.map do |job|
|
|
213
151
|
delayed = job.scheduled_at && job.scheduled_at < now
|
|
214
152
|
{
|
|
215
153
|
id: job.id,
|
|
@@ -235,47 +173,6 @@ module SolidQueueTui
|
|
|
235
173
|
table.render(frame, area, @table_state)
|
|
236
174
|
end
|
|
237
175
|
|
|
238
|
-
def render_confirm(frame, area)
|
|
239
|
-
message = case @confirm_action
|
|
240
|
-
when :run_now
|
|
241
|
-
job = selected_item
|
|
242
|
-
"Run job ##{job&.id} (#{job&.class_name}) now? [y/n]"
|
|
243
|
-
when :discard
|
|
244
|
-
job = selected_item
|
|
245
|
-
"Discard job ##{job&.id} (#{job&.class_name})? This cannot be undone. [y/n]"
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
frame.render_widget(
|
|
249
|
-
@tui.paragraph(
|
|
250
|
-
text: " #{message}",
|
|
251
|
-
style: @tui.style(fg: :yellow, modifiers: [:bold]),
|
|
252
|
-
block: @tui.block(
|
|
253
|
-
title: " Confirm ",
|
|
254
|
-
title_style: @tui.style(fg: :red, modifiers: [:bold]),
|
|
255
|
-
borders: [:all],
|
|
256
|
-
border_type: :rounded,
|
|
257
|
-
border_style: @tui.style(fg: :red)
|
|
258
|
-
)
|
|
259
|
-
),
|
|
260
|
-
area
|
|
261
|
-
)
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def format_time(time)
|
|
265
|
-
return "n/a" unless time
|
|
266
|
-
time.strftime("%Y-%m-%d %H:%M:%S")
|
|
267
|
-
end
|
|
268
|
-
|
|
269
|
-
def time_ago(time)
|
|
270
|
-
return "n/a" unless time
|
|
271
|
-
seconds = (Time.now.utc - time).to_i
|
|
272
|
-
case seconds
|
|
273
|
-
when 0..59 then "#{seconds}s ago"
|
|
274
|
-
when 60..3599 then "#{seconds / 60}m ago"
|
|
275
|
-
when 3600..86399 then "#{seconds / 3600}h ago"
|
|
276
|
-
else "#{seconds / 86400}d ago"
|
|
277
|
-
end
|
|
278
|
-
end
|
|
279
176
|
end
|
|
280
177
|
end
|
|
281
178
|
end
|
data/lib/solid_queue_tui.rb
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative "solid_queue_tui/version"
|
|
4
|
+
require_relative "solid_queue_tui/formatting_helpers"
|
|
4
5
|
|
|
5
6
|
# Data layer
|
|
6
7
|
require_relative "solid_queue_tui/data/stats"
|
|
8
|
+
require_relative "solid_queue_tui/data/hourly_stats_query"
|
|
7
9
|
require_relative "solid_queue_tui/data/jobs_query"
|
|
8
10
|
require_relative "solid_queue_tui/data/queues_query"
|
|
9
11
|
require_relative "solid_queue_tui/data/processes_query"
|
|
@@ -25,6 +27,8 @@ require_relative "solid_queue_tui/components/help_bar"
|
|
|
25
27
|
|
|
26
28
|
# View concerns
|
|
27
29
|
require_relative "solid_queue_tui/views/concerns/filterable"
|
|
30
|
+
require_relative "solid_queue_tui/views/concerns/confirmable"
|
|
31
|
+
require_relative "solid_queue_tui/views/concerns/paginatable"
|
|
28
32
|
|
|
29
33
|
# Views
|
|
30
34
|
require_relative "solid_queue_tui/views/dashboard_view"
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: solid_queue_tui
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Shiva Reddy
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ratatui_ruby
|
|
@@ -84,11 +84,13 @@ description: Real-time terminal dashboard to monitor and manage Solid Queue jobs
|
|
|
84
84
|
Built with ratatui_ruby for native Rust rendering performance.
|
|
85
85
|
email:
|
|
86
86
|
executables:
|
|
87
|
+
- qtop
|
|
87
88
|
- sqtui
|
|
88
89
|
extensions: []
|
|
89
90
|
extra_rdoc_files: []
|
|
90
91
|
files:
|
|
91
92
|
- LICENSE.txt
|
|
93
|
+
- exe/qtop
|
|
92
94
|
- exe/sqtui
|
|
93
95
|
- lib/solid_queue_tui.rb
|
|
94
96
|
- lib/solid_queue_tui/actions/discard_job.rb
|
|
@@ -103,16 +105,20 @@ files:
|
|
|
103
105
|
- lib/solid_queue_tui/components/help_bar.rb
|
|
104
106
|
- lib/solid_queue_tui/components/job_table.rb
|
|
105
107
|
- lib/solid_queue_tui/data/failed_query.rb
|
|
108
|
+
- lib/solid_queue_tui/data/hourly_stats_query.rb
|
|
106
109
|
- lib/solid_queue_tui/data/jobs_query.rb
|
|
107
110
|
- lib/solid_queue_tui/data/processes_query.rb
|
|
108
111
|
- lib/solid_queue_tui/data/queues_query.rb
|
|
109
112
|
- lib/solid_queue_tui/data/recurring_tasks_query.rb
|
|
110
113
|
- lib/solid_queue_tui/data/stats.rb
|
|
111
114
|
- lib/solid_queue_tui/dev_reloader.rb
|
|
115
|
+
- lib/solid_queue_tui/formatting_helpers.rb
|
|
112
116
|
- lib/solid_queue_tui/railtie.rb
|
|
113
117
|
- lib/solid_queue_tui/version.rb
|
|
114
118
|
- lib/solid_queue_tui/views/blocked_view.rb
|
|
119
|
+
- lib/solid_queue_tui/views/concerns/confirmable.rb
|
|
115
120
|
- lib/solid_queue_tui/views/concerns/filterable.rb
|
|
121
|
+
- lib/solid_queue_tui/views/concerns/paginatable.rb
|
|
116
122
|
- lib/solid_queue_tui/views/dashboard_view.rb
|
|
117
123
|
- lib/solid_queue_tui/views/failed_view.rb
|
|
118
124
|
- lib/solid_queue_tui/views/finished_view.rb
|
|
@@ -135,7 +141,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
135
141
|
requirements:
|
|
136
142
|
- - ">="
|
|
137
143
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: 3.2.
|
|
144
|
+
version: 3.2.9
|
|
139
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
146
|
requirements:
|
|
141
147
|
- - ">="
|