solid_queue_monitor 1.0.0 → 1.1.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/README.md +3 -1
- data/app/controllers/solid_queue_monitor/base_controller.rb +34 -2
- data/app/controllers/solid_queue_monitor/failed_jobs_controller.rb +7 -3
- data/app/controllers/solid_queue_monitor/in_progress_jobs_controller.rb +7 -3
- data/app/controllers/solid_queue_monitor/overview_controller.rb +7 -3
- data/app/controllers/solid_queue_monitor/queues_controller.rb +21 -8
- data/app/controllers/solid_queue_monitor/ready_jobs_controller.rb +7 -3
- data/app/controllers/solid_queue_monitor/recurring_jobs_controller.rb +7 -3
- data/app/controllers/solid_queue_monitor/scheduled_jobs_controller.rb +7 -3
- data/app/controllers/solid_queue_monitor/search_controller.rb +12 -0
- data/app/controllers/solid_queue_monitor/workers_controller.rb +7 -4
- data/app/presenters/solid_queue_monitor/base_presenter.rb +47 -5
- data/app/presenters/solid_queue_monitor/failed_jobs_presenter.rb +6 -6
- data/app/presenters/solid_queue_monitor/in_progress_jobs_presenter.rb +5 -4
- data/app/presenters/solid_queue_monitor/jobs_presenter.rb +5 -4
- data/app/presenters/solid_queue_monitor/queue_details_presenter.rb +4 -3
- data/app/presenters/solid_queue_monitor/queues_presenter.rb +4 -3
- data/app/presenters/solid_queue_monitor/ready_jobs_presenter.rb +6 -5
- data/app/presenters/solid_queue_monitor/recurring_jobs_presenter.rb +6 -5
- data/app/presenters/solid_queue_monitor/scheduled_jobs_presenter.rb +5 -4
- data/app/presenters/solid_queue_monitor/search_results_presenter.rb +190 -0
- data/app/presenters/solid_queue_monitor/workers_presenter.rb +4 -3
- data/app/services/solid_queue_monitor/html_generator.rb +23 -2
- data/app/services/solid_queue_monitor/search_service.rb +126 -0
- data/app/services/solid_queue_monitor/stylesheet_generator.rb +614 -0
- data/config/routes.rb +1 -0
- data/lib/solid_queue_monitor/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1014e5b1b9afceff146efc3a81849dd12866578198b8172452d9b6edf42d7786
|
|
4
|
+
data.tar.gz: 0b2c11f5ba47a7e977c93cdb7a048c91d092b9ea97d72af27e908f6f24387fbf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 58bf74bb26fbb518d58e555d1a22695d3175b0ea683529685b4cec6322091722fd7a8eb912bb0fbbfa0fce391663777fc69cde137bf4a4cb0fb1e1cf9d16bbf2
|
|
7
|
+
data.tar.gz: 59be98bcc8ee044ac0eac816cab397534c79da53cb98cfb670da1e0747552425f33eaf6dce51e2f906c44f9053b4097a8a79e3f2d6fe30534ddbad6e7f3d3d70
|
data/README.md
CHANGED
|
@@ -35,6 +35,8 @@ A lightweight, zero-dependency web interface for monitoring Solid Queue backgrou
|
|
|
35
35
|
- **Failed Jobs**: Track and debug failed jobs, with the ability to retry or discard them
|
|
36
36
|
- **Queue Management**: View and filter jobs by queue with pause/resume controls
|
|
37
37
|
- **Pause/Resume Queues**: Temporarily stop processing jobs on specific queues for incident response
|
|
38
|
+
- **Global Search**: Search across all job types by class name, queue, arguments, job ID, and error messages
|
|
39
|
+
- **Sortable Columns**: Click column headers to sort job tables by any column with ascending/descending toggle
|
|
38
40
|
- **Advanced Job Filtering**: Filter jobs by class name, queue, status, and job arguments
|
|
39
41
|
- **Quick Actions**: Retry or discard failed jobs, execute or reject scheduled jobs directly from any view
|
|
40
42
|
- **Performance Optimized**: Designed for high-volume applications with smart pagination
|
|
@@ -70,7 +72,7 @@ A lightweight, zero-dependency web interface for monitoring Solid Queue backgrou
|
|
|
70
72
|
Add this line to your application's Gemfile:
|
|
71
73
|
|
|
72
74
|
```ruby
|
|
73
|
-
gem 'solid_queue_monitor', '~> 1.
|
|
75
|
+
gem 'solid_queue_monitor', '~> 1.1'
|
|
74
76
|
```
|
|
75
77
|
|
|
76
78
|
Then execute:
|
|
@@ -6,7 +6,7 @@ module SolidQueueMonitor
|
|
|
6
6
|
PaginationService.new(relation, current_page, per_page).paginate
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def render_page(title, content)
|
|
9
|
+
def render_page(title, content, search_query: nil)
|
|
10
10
|
# Get flash message from instance variable (set by set_flash_message) or session
|
|
11
11
|
message = @flash_message
|
|
12
12
|
message_type = @flash_type
|
|
@@ -27,7 +27,8 @@ module SolidQueueMonitor
|
|
|
27
27
|
title: title,
|
|
28
28
|
content: content,
|
|
29
29
|
message: message,
|
|
30
|
-
message_type: message_type
|
|
30
|
+
message_type: message_type,
|
|
31
|
+
search_query: search_query
|
|
31
32
|
).generate
|
|
32
33
|
|
|
33
34
|
render html: html.html_safe
|
|
@@ -201,5 +202,36 @@ module SolidQueueMonitor
|
|
|
201
202
|
status: params[:status]
|
|
202
203
|
}
|
|
203
204
|
end
|
|
205
|
+
|
|
206
|
+
def sort_params
|
|
207
|
+
{
|
|
208
|
+
sort_by: params[:sort_by],
|
|
209
|
+
sort_direction: params[:sort_direction]
|
|
210
|
+
}
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def apply_sorting(relation, allowed_columns, default_column, default_direction = :desc)
|
|
214
|
+
column = sort_params[:sort_by]
|
|
215
|
+
direction = sort_params[:sort_direction]
|
|
216
|
+
column = default_column unless allowed_columns.include?(column)
|
|
217
|
+
direction = %w[asc desc].include?(direction) ? direction.to_sym : default_direction
|
|
218
|
+
relation.order(column => direction)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def apply_execution_sorting(relation, allowed_columns, default_column, default_direction = :desc)
|
|
222
|
+
column = sort_params[:sort_by]
|
|
223
|
+
direction = sort_params[:sort_direction]
|
|
224
|
+
column = default_column unless allowed_columns.include?(column)
|
|
225
|
+
direction = %w[asc desc].include?(direction) ? direction.to_sym : default_direction
|
|
226
|
+
|
|
227
|
+
# Columns that exist on the jobs table, not on execution tables
|
|
228
|
+
job_table_columns = %w[class_name queue_name]
|
|
229
|
+
|
|
230
|
+
if job_table_columns.include?(column)
|
|
231
|
+
relation.joins(:job).order("solid_queue_jobs.#{column}" => direction)
|
|
232
|
+
else
|
|
233
|
+
relation.order(column => direction)
|
|
234
|
+
end
|
|
235
|
+
end
|
|
204
236
|
end
|
|
205
237
|
end
|
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class FailedJobsController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[class_name queue_name created_at].freeze
|
|
6
|
+
|
|
5
7
|
def index
|
|
6
|
-
base_query = SolidQueue::FailedExecution.includes(:job)
|
|
7
|
-
|
|
8
|
+
base_query = SolidQueue::FailedExecution.includes(:job)
|
|
9
|
+
sorted_query = apply_execution_sorting(filter_failed_jobs(base_query), SORTABLE_COLUMNS, 'created_at', :desc)
|
|
10
|
+
@failed_jobs = paginate(sorted_query)
|
|
8
11
|
|
|
9
12
|
render_page('Failed Jobs', SolidQueueMonitor::FailedJobsPresenter.new(@failed_jobs[:records],
|
|
10
13
|
current_page: @failed_jobs[:current_page],
|
|
11
14
|
total_pages: @failed_jobs[:total_pages],
|
|
12
|
-
filters: filter_params
|
|
15
|
+
filters: filter_params,
|
|
16
|
+
sort: sort_params).render)
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
def retry
|
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class InProgressJobsController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[class_name queue_name created_at].freeze
|
|
6
|
+
|
|
5
7
|
def index
|
|
6
|
-
base_query = SolidQueue::ClaimedExecution.includes(:job)
|
|
7
|
-
|
|
8
|
+
base_query = SolidQueue::ClaimedExecution.includes(:job)
|
|
9
|
+
sorted_query = apply_execution_sorting(filter_in_progress_jobs(base_query), SORTABLE_COLUMNS, 'created_at', :desc)
|
|
10
|
+
@in_progress_jobs = paginate(sorted_query)
|
|
8
11
|
|
|
9
12
|
render_page('In Progress Jobs', SolidQueueMonitor::InProgressJobsPresenter.new(@in_progress_jobs[:records],
|
|
10
13
|
current_page: @in_progress_jobs[:current_page],
|
|
11
14
|
total_pages: @in_progress_jobs[:total_pages],
|
|
12
|
-
filters: filter_params
|
|
15
|
+
filters: filter_params,
|
|
16
|
+
sort: sort_params).render)
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
private
|
|
@@ -2,12 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class OverviewController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[class_name queue_name created_at].freeze
|
|
6
|
+
|
|
5
7
|
def index
|
|
6
8
|
@stats = SolidQueueMonitor::StatsCalculator.calculate
|
|
7
9
|
@chart_data = SolidQueueMonitor::ChartDataService.new(time_range: time_range_param).calculate
|
|
8
10
|
|
|
9
|
-
recent_jobs_query = SolidQueue::Job.
|
|
10
|
-
|
|
11
|
+
recent_jobs_query = SolidQueue::Job.limit(100)
|
|
12
|
+
sorted_query = apply_sorting(filter_jobs(recent_jobs_query), SORTABLE_COLUMNS, 'created_at', :desc)
|
|
13
|
+
@recent_jobs = paginate(sorted_query)
|
|
11
14
|
|
|
12
15
|
preload_job_statuses(@recent_jobs[:records])
|
|
13
16
|
|
|
@@ -31,7 +34,8 @@ module SolidQueueMonitor
|
|
|
31
34
|
SolidQueueMonitor::JobsPresenter.new(@recent_jobs[:records],
|
|
32
35
|
current_page: @recent_jobs[:current_page],
|
|
33
36
|
total_pages: @recent_jobs[:total_pages],
|
|
34
|
-
filters: filter_params
|
|
37
|
+
filters: filter_params,
|
|
38
|
+
sort: sort_params).render
|
|
35
39
|
end
|
|
36
40
|
end
|
|
37
41
|
end
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class QueuesController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[queue_name job_count].freeze
|
|
6
|
+
QUEUE_DETAILS_SORTABLE_COLUMNS = %w[class_name created_at].freeze
|
|
7
|
+
|
|
5
8
|
def index
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
base_query = SolidQueue::Job.group(:queue_name)
|
|
10
|
+
.select('queue_name, COUNT(*) as job_count')
|
|
11
|
+
@queues = apply_queue_sorting(base_query)
|
|
9
12
|
@paused_queues = QueuePauseService.paused_queues
|
|
10
13
|
|
|
11
|
-
render_page('Queues', SolidQueueMonitor::QueuesPresenter.new(@queues, @paused_queues).render)
|
|
14
|
+
render_page('Queues', SolidQueueMonitor::QueuesPresenter.new(@queues, @paused_queues, sort: sort_params).render)
|
|
12
15
|
end
|
|
13
16
|
|
|
14
17
|
def show
|
|
@@ -16,9 +19,9 @@ module SolidQueueMonitor
|
|
|
16
19
|
@paused = QueuePauseService.paused_queues.include?(@queue_name)
|
|
17
20
|
|
|
18
21
|
# Get all jobs for this queue with filtering and pagination
|
|
19
|
-
base_query = SolidQueue::Job.where(queue_name: @queue_name)
|
|
20
|
-
|
|
21
|
-
@jobs = paginate(
|
|
22
|
+
base_query = SolidQueue::Job.where(queue_name: @queue_name)
|
|
23
|
+
sorted_query = apply_sorting(filter_queue_jobs(base_query), QUEUE_DETAILS_SORTABLE_COLUMNS, 'created_at', :desc)
|
|
24
|
+
@jobs = paginate(sorted_query)
|
|
22
25
|
preload_job_statuses(@jobs[:records])
|
|
23
26
|
|
|
24
27
|
@counts = calculate_queue_counts(@queue_name)
|
|
@@ -31,7 +34,8 @@ module SolidQueueMonitor
|
|
|
31
34
|
counts: @counts,
|
|
32
35
|
current_page: @jobs[:current_page],
|
|
33
36
|
total_pages: @jobs[:total_pages],
|
|
34
|
-
filters: queue_filter_params
|
|
37
|
+
filters: queue_filter_params,
|
|
38
|
+
sort: sort_params
|
|
35
39
|
).render)
|
|
36
40
|
end
|
|
37
41
|
|
|
@@ -97,5 +101,14 @@ module SolidQueueMonitor
|
|
|
97
101
|
status: params[:status]
|
|
98
102
|
}
|
|
99
103
|
end
|
|
104
|
+
|
|
105
|
+
def apply_queue_sorting(relation)
|
|
106
|
+
column = sort_params[:sort_by]
|
|
107
|
+
direction = sort_params[:sort_direction]
|
|
108
|
+
column = 'job_count' unless SORTABLE_COLUMNS.include?(column)
|
|
109
|
+
direction = 'desc' unless %w[asc desc].include?(direction)
|
|
110
|
+
|
|
111
|
+
relation.order("#{column} #{direction}")
|
|
112
|
+
end
|
|
100
113
|
end
|
|
101
114
|
end
|
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class ReadyJobsController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[class_name queue_name priority created_at].freeze
|
|
6
|
+
|
|
5
7
|
def index
|
|
6
|
-
base_query = SolidQueue::ReadyExecution.includes(:job)
|
|
7
|
-
|
|
8
|
+
base_query = SolidQueue::ReadyExecution.includes(:job)
|
|
9
|
+
sorted_query = apply_execution_sorting(filter_ready_jobs(base_query), SORTABLE_COLUMNS, 'created_at', :desc)
|
|
10
|
+
@ready_jobs = paginate(sorted_query)
|
|
8
11
|
|
|
9
12
|
render_page('Ready Jobs', SolidQueueMonitor::ReadyJobsPresenter.new(@ready_jobs[:records],
|
|
10
13
|
current_page: @ready_jobs[:current_page],
|
|
11
14
|
total_pages: @ready_jobs[:total_pages],
|
|
12
|
-
filters: filter_params
|
|
15
|
+
filters: filter_params,
|
|
16
|
+
sort: sort_params).render)
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
end
|
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class RecurringJobsController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[key class_name queue_name priority].freeze
|
|
6
|
+
|
|
5
7
|
def index
|
|
6
|
-
base_query = filter_recurring_jobs(SolidQueue::RecurringTask.
|
|
7
|
-
|
|
8
|
+
base_query = filter_recurring_jobs(SolidQueue::RecurringTask.all)
|
|
9
|
+
sorted_query = apply_sorting(base_query, SORTABLE_COLUMNS, 'key', :asc)
|
|
10
|
+
@recurring_jobs = paginate(sorted_query)
|
|
8
11
|
|
|
9
12
|
render_page('Recurring Jobs', SolidQueueMonitor::RecurringJobsPresenter.new(@recurring_jobs[:records],
|
|
10
13
|
current_page: @recurring_jobs[:current_page],
|
|
11
14
|
total_pages: @recurring_jobs[:total_pages],
|
|
12
|
-
filters: filter_params
|
|
15
|
+
filters: filter_params,
|
|
16
|
+
sort: sort_params).render)
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
end
|
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class ScheduledJobsController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[class_name queue_name scheduled_at].freeze
|
|
6
|
+
|
|
5
7
|
def index
|
|
6
|
-
base_query = SolidQueue::ScheduledExecution.includes(:job)
|
|
7
|
-
|
|
8
|
+
base_query = SolidQueue::ScheduledExecution.includes(:job)
|
|
9
|
+
sorted_query = apply_execution_sorting(filter_scheduled_jobs(base_query), SORTABLE_COLUMNS, 'scheduled_at', :asc)
|
|
10
|
+
@scheduled_jobs = paginate(sorted_query)
|
|
8
11
|
|
|
9
12
|
render_page('Scheduled Jobs', SolidQueueMonitor::ScheduledJobsPresenter.new(@scheduled_jobs[:records],
|
|
10
13
|
current_page: @scheduled_jobs[:current_page],
|
|
11
14
|
total_pages: @scheduled_jobs[:total_pages],
|
|
12
|
-
filters: filter_params
|
|
15
|
+
filters: filter_params,
|
|
16
|
+
sort: sort_params).render)
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
def create
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SolidQueueMonitor
|
|
4
|
+
class SearchController < BaseController
|
|
5
|
+
def index
|
|
6
|
+
query = params[:q]
|
|
7
|
+
results = SearchService.new(query).search
|
|
8
|
+
|
|
9
|
+
render_page('Search', SearchResultsPresenter.new(query, results).render, search_query: query)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -2,16 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class WorkersController < BaseController
|
|
5
|
+
SORTABLE_COLUMNS = %w[hostname last_heartbeat_at].freeze
|
|
6
|
+
|
|
5
7
|
def index
|
|
6
|
-
base_query = SolidQueue::Process.
|
|
7
|
-
|
|
8
|
-
@processes = paginate(
|
|
8
|
+
base_query = SolidQueue::Process.all
|
|
9
|
+
sorted_query = apply_sorting(filter_workers(base_query), SORTABLE_COLUMNS, 'last_heartbeat_at', :desc)
|
|
10
|
+
@processes = paginate(sorted_query)
|
|
9
11
|
|
|
10
12
|
render_page('Workers', SolidQueueMonitor::WorkersPresenter.new(
|
|
11
13
|
@processes[:records],
|
|
12
14
|
current_page: @processes[:current_page],
|
|
13
15
|
total_pages: @processes[:total_pages],
|
|
14
|
-
filters: worker_filter_params
|
|
16
|
+
filters: worker_filter_params,
|
|
17
|
+
sort: sort_params
|
|
15
18
|
).render)
|
|
16
19
|
end
|
|
17
20
|
|
|
@@ -118,6 +118,34 @@ module SolidQueueMonitor
|
|
|
118
118
|
"<a href=\"#{queue_details_path(queue_name: queue_name)}\" class=\"#{classes}\">#{queue_name}</a>"
|
|
119
119
|
end
|
|
120
120
|
|
|
121
|
+
def sortable_header(column, label)
|
|
122
|
+
return "<th>#{label}</th>" unless @sort
|
|
123
|
+
|
|
124
|
+
column_str = column.to_s
|
|
125
|
+
is_active = @sort[:sort_by] == column_str
|
|
126
|
+
next_direction = is_active && @sort[:sort_direction] == 'asc' ? 'desc' : 'asc'
|
|
127
|
+
arrow = sort_arrow(is_active)
|
|
128
|
+
css_class = is_active ? 'sortable-header active' : 'sortable-header'
|
|
129
|
+
|
|
130
|
+
"<th><a href=\"?sort_by=#{column}&sort_direction=#{next_direction}#{filter_query_string}\" class=\"#{css_class}\">#{label}#{arrow}</a></th>"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def sort_arrow(is_active)
|
|
134
|
+
return ' ⇅' unless is_active
|
|
135
|
+
|
|
136
|
+
@sort[:sort_direction] == 'asc' ? ' ↑' : ' ↓'
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def filter_query_string
|
|
140
|
+
params = []
|
|
141
|
+
params << "class_name=#{@filters[:class_name]}" if @filters && @filters[:class_name].present?
|
|
142
|
+
params << "queue_name=#{@filters[:queue_name]}" if @filters && @filters[:queue_name].present?
|
|
143
|
+
params << "arguments=#{@filters[:arguments]}" if @filters && @filters[:arguments].present?
|
|
144
|
+
params << "status=#{@filters[:status]}" if @filters && @filters[:status].present?
|
|
145
|
+
|
|
146
|
+
params.empty? ? '' : "&#{params.join('&')}"
|
|
147
|
+
end
|
|
148
|
+
|
|
121
149
|
def request_path
|
|
122
150
|
if defined?(controller) && controller.respond_to?(:request)
|
|
123
151
|
controller.request.path
|
|
@@ -138,14 +166,28 @@ module SolidQueueMonitor
|
|
|
138
166
|
private
|
|
139
167
|
|
|
140
168
|
def query_params
|
|
141
|
-
params =
|
|
142
|
-
params << "class_name=#{@filters[:class_name]}" if @filters && @filters[:class_name].present?
|
|
143
|
-
params << "queue_name=#{@filters[:queue_name]}" if @filters && @filters[:queue_name].present?
|
|
144
|
-
params << "status=#{@filters[:status]}" if @filters && @filters[:status].present?
|
|
145
|
-
|
|
169
|
+
params = build_filter_params + build_sort_params
|
|
146
170
|
params.empty? ? '' : "&#{params.join('&')}"
|
|
147
171
|
end
|
|
148
172
|
|
|
173
|
+
def build_filter_params
|
|
174
|
+
return [] unless @filters
|
|
175
|
+
|
|
176
|
+
filter_keys = %i[class_name queue_name status]
|
|
177
|
+
filter_keys.filter_map do |key|
|
|
178
|
+
"#{key}=#{@filters[key]}" if @filters[key].present?
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def build_sort_params
|
|
183
|
+
return [] unless @sort
|
|
184
|
+
|
|
185
|
+
sort_keys = %i[sort_by sort_direction]
|
|
186
|
+
sort_keys.filter_map do |key|
|
|
187
|
+
"#{key}=#{@sort[key]}" if @sort[key].present?
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
149
191
|
def full_path(route_name, *args)
|
|
150
192
|
SolidQueueMonitor::Engine.routes.url_helpers.send(route_name, *args)
|
|
151
193
|
rescue NoMethodError
|
|
@@ -5,11 +5,12 @@ module SolidQueueMonitor
|
|
|
5
5
|
include Rails.application.routes.url_helpers
|
|
6
6
|
include SolidQueueMonitor::Engine.routes.url_helpers
|
|
7
7
|
|
|
8
|
-
def initialize(jobs, current_page: 1, total_pages: 1, filters: {})
|
|
8
|
+
def initialize(jobs, current_page: 1, total_pages: 1, filters: {}, sort: {})
|
|
9
9
|
@jobs = jobs
|
|
10
10
|
@current_page = current_page
|
|
11
11
|
@total_pages = total_pages
|
|
12
12
|
@filters = filters
|
|
13
|
+
@sort = sort
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def render
|
|
@@ -60,10 +61,11 @@ module SolidQueueMonitor
|
|
|
60
61
|
<thead>
|
|
61
62
|
<tr>
|
|
62
63
|
<th><input type="checkbox" id="select-all" class="select-all-checkbox"></th>
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
#{sortable_header('class_name', 'Job')}
|
|
65
|
+
#{sortable_header('queue_name', 'Queue')}
|
|
65
66
|
<th>Error</th>
|
|
66
67
|
<th>Arguments</th>
|
|
68
|
+
#{sortable_header('created_at', 'Failed At')}
|
|
67
69
|
<th>Actions</th>
|
|
68
70
|
</tr>
|
|
69
71
|
</thead>
|
|
@@ -261,11 +263,9 @@ module SolidQueueMonitor
|
|
|
261
263
|
</td>
|
|
262
264
|
<td>
|
|
263
265
|
<div class="error-message">#{error[:message].to_s.truncate(100)}</div>
|
|
264
|
-
<div class="job-meta">
|
|
265
|
-
<span class="job-timestamp">Failed at: #{format_datetime(failed_execution.created_at)}</span>
|
|
266
|
-
</div>
|
|
267
266
|
</td>
|
|
268
267
|
<td>#{format_arguments(job.arguments)}</td>
|
|
268
|
+
<td>#{format_datetime(failed_execution.created_at)}</td>
|
|
269
269
|
<td class="actions-cell">
|
|
270
270
|
<div class="job-actions">
|
|
271
271
|
<a href="javascript:void(0)"#{' '}
|
|
@@ -4,11 +4,12 @@ module SolidQueueMonitor
|
|
|
4
4
|
class InProgressJobsPresenter < BasePresenter
|
|
5
5
|
include SolidQueueMonitor::Engine.routes.url_helpers
|
|
6
6
|
|
|
7
|
-
def initialize(jobs, current_page: 1, total_pages: 1, filters: {})
|
|
7
|
+
def initialize(jobs, current_page: 1, total_pages: 1, filters: {}, sort: {})
|
|
8
8
|
@jobs = jobs
|
|
9
9
|
@current_page = current_page
|
|
10
10
|
@total_pages = total_pages
|
|
11
11
|
@filters = filters
|
|
12
|
+
@sort = sort
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def render
|
|
@@ -47,10 +48,10 @@ module SolidQueueMonitor
|
|
|
47
48
|
<table>
|
|
48
49
|
<thead>
|
|
49
50
|
<tr>
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
#{sortable_header('class_name', 'Job')}
|
|
52
|
+
#{sortable_header('queue_name', 'Queue')}
|
|
52
53
|
<th>Arguments</th>
|
|
53
|
-
|
|
54
|
+
#{sortable_header('created_at', 'Started At')}
|
|
54
55
|
<th>Process ID</th>
|
|
55
56
|
</tr>
|
|
56
57
|
</thead>
|
|
@@ -5,11 +5,12 @@ module SolidQueueMonitor
|
|
|
5
5
|
include Rails.application.routes.url_helpers
|
|
6
6
|
include SolidQueueMonitor::Engine.routes.url_helpers
|
|
7
7
|
|
|
8
|
-
def initialize(jobs, current_page: 1, total_pages: 1, filters: {})
|
|
8
|
+
def initialize(jobs, current_page: 1, total_pages: 1, filters: {}, sort: {})
|
|
9
9
|
@jobs = jobs
|
|
10
10
|
@current_page = current_page
|
|
11
11
|
@total_pages = total_pages
|
|
12
12
|
@filters = filters
|
|
13
|
+
@sort = sort
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def render
|
|
@@ -73,11 +74,11 @@ module SolidQueueMonitor
|
|
|
73
74
|
<thead>
|
|
74
75
|
<tr>
|
|
75
76
|
<th>ID</th>
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
#{sortable_header('class_name', 'Job')}
|
|
78
|
+
#{sortable_header('queue_name', 'Queue')}
|
|
78
79
|
<th>Arguments</th>
|
|
79
80
|
<th>Status</th>
|
|
80
|
-
|
|
81
|
+
#{sortable_header('created_at', 'Created At')}
|
|
81
82
|
<th>Actions</th>
|
|
82
83
|
</tr>
|
|
83
84
|
</thead>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class QueueDetailsPresenter < BasePresenter
|
|
5
|
-
def initialize(queue_name:, paused:, jobs:, counts:, current_page: 1, total_pages: 1, filters: {})
|
|
5
|
+
def initialize(queue_name:, paused:, jobs:, counts:, current_page: 1, total_pages: 1, filters: {}, sort: {})
|
|
6
6
|
@queue_name = queue_name
|
|
7
7
|
@paused = paused
|
|
8
8
|
@jobs = jobs
|
|
@@ -10,6 +10,7 @@ module SolidQueueMonitor
|
|
|
10
10
|
@current_page = current_page
|
|
11
11
|
@total_pages = total_pages
|
|
12
12
|
@filters = filters
|
|
13
|
+
@sort = sort
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def render
|
|
@@ -129,10 +130,10 @@ module SolidQueueMonitor
|
|
|
129
130
|
<thead>
|
|
130
131
|
<tr>
|
|
131
132
|
<th>ID</th>
|
|
132
|
-
|
|
133
|
+
#{sortable_header('class_name', 'Job')}
|
|
133
134
|
<th>Arguments</th>
|
|
134
135
|
<th>Status</th>
|
|
135
|
-
|
|
136
|
+
#{sortable_header('created_at', 'Created At')}
|
|
136
137
|
<th>Actions</th>
|
|
137
138
|
</tr>
|
|
138
139
|
</thead>
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class QueuesPresenter < BasePresenter
|
|
5
|
-
def initialize(records, paused_queues = [])
|
|
5
|
+
def initialize(records, paused_queues = [], sort: {})
|
|
6
6
|
@records = records
|
|
7
7
|
@paused_queues = paused_queues
|
|
8
|
+
@sort = sort
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def render
|
|
@@ -19,9 +20,9 @@ module SolidQueueMonitor
|
|
|
19
20
|
<table>
|
|
20
21
|
<thead>
|
|
21
22
|
<tr>
|
|
22
|
-
|
|
23
|
+
#{sortable_header('queue_name', 'Queue Name')}
|
|
23
24
|
<th>Status</th>
|
|
24
|
-
|
|
25
|
+
#{sortable_header('job_count', 'Total Jobs')}
|
|
25
26
|
<th>Ready Jobs</th>
|
|
26
27
|
<th>Scheduled Jobs</th>
|
|
27
28
|
<th>Failed Jobs</th>
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
module SolidQueueMonitor
|
|
4
4
|
class ReadyJobsPresenter < BasePresenter
|
|
5
|
-
def initialize(jobs, current_page: 1, total_pages: 1, filters: {})
|
|
5
|
+
def initialize(jobs, current_page: 1, total_pages: 1, filters: {}, sort: {})
|
|
6
6
|
@jobs = jobs
|
|
7
7
|
@current_page = current_page
|
|
8
8
|
@total_pages = total_pages
|
|
9
9
|
@filters = filters
|
|
10
|
+
@sort = sort
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def render
|
|
@@ -50,11 +51,11 @@ module SolidQueueMonitor
|
|
|
50
51
|
<table>
|
|
51
52
|
<thead>
|
|
52
53
|
<tr>
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
#{sortable_header('class_name', 'Job')}
|
|
55
|
+
#{sortable_header('queue_name', 'Queue')}
|
|
56
|
+
#{sortable_header('priority', 'Priority')}
|
|
56
57
|
<th>Arguments</th>
|
|
57
|
-
|
|
58
|
+
#{sortable_header('created_at', 'Created At')}
|
|
58
59
|
</tr>
|
|
59
60
|
</thead>
|
|
60
61
|
<tbody>
|
|
@@ -5,11 +5,12 @@ module SolidQueueMonitor
|
|
|
5
5
|
include Rails.application.routes.url_helpers
|
|
6
6
|
include SolidQueueMonitor::Engine.routes.url_helpers
|
|
7
7
|
|
|
8
|
-
def initialize(jobs, current_page: 1, total_pages: 1, filters: {})
|
|
8
|
+
def initialize(jobs, current_page: 1, total_pages: 1, filters: {}, sort: {})
|
|
9
9
|
@jobs = jobs
|
|
10
10
|
@current_page = current_page
|
|
11
11
|
@total_pages = total_pages
|
|
12
12
|
@filters = filters
|
|
13
|
+
@sort = sort
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def render
|
|
@@ -48,11 +49,11 @@ module SolidQueueMonitor
|
|
|
48
49
|
<table>
|
|
49
50
|
<thead>
|
|
50
51
|
<tr>
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
#{sortable_header('key', 'Key')}
|
|
53
|
+
#{sortable_header('class_name', 'Job')}
|
|
53
54
|
<th>Schedule</th>
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
#{sortable_header('queue_name', 'Queue')}
|
|
56
|
+
#{sortable_header('priority', 'Priority')}
|
|
56
57
|
<th>Last Updated</th>
|
|
57
58
|
</tr>
|
|
58
59
|
</thead>
|
|
@@ -5,11 +5,12 @@ module SolidQueueMonitor
|
|
|
5
5
|
include Rails.application.routes.url_helpers
|
|
6
6
|
include SolidQueueMonitor::Engine.routes.url_helpers
|
|
7
7
|
|
|
8
|
-
def initialize(jobs, current_page: 1, total_pages: 1, filters: {})
|
|
8
|
+
def initialize(jobs, current_page: 1, total_pages: 1, filters: {}, sort: {})
|
|
9
9
|
@jobs = jobs
|
|
10
10
|
@current_page = current_page
|
|
11
11
|
@total_pages = total_pages
|
|
12
12
|
@filters = filters
|
|
13
|
+
@sort = sort
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def render
|
|
@@ -140,9 +141,9 @@ module SolidQueueMonitor
|
|
|
140
141
|
<thead>
|
|
141
142
|
<tr>
|
|
142
143
|
<th width="50"><input type="checkbox"></th>
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
#{sortable_header('class_name', 'Job')}
|
|
145
|
+
#{sortable_header('queue_name', 'Queue')}
|
|
146
|
+
#{sortable_header('scheduled_at', 'Scheduled At')}
|
|
146
147
|
<th>Arguments</th>
|
|
147
148
|
</tr>
|
|
148
149
|
</thead>
|