que-view 0.1.0 → 0.2.1
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 +36 -9
- data/app/assets/stylesheets/que/view/application.css +36 -10
- data/app/controllers/que/view/application_controller.rb +14 -0
- data/app/controllers/que/view/jobs_controller.rb +55 -4
- data/app/controllers/que/view/welcome_controller.rb +1 -1
- data/app/helpers/que/view/application_helper.rb +0 -2
- data/app/views/que/view/jobs/index.html.erb +29 -9
- data/app/views/que/view/jobs/show.html.erb +51 -0
- data/app/views/que/view/welcome/index.html.erb +16 -12
- data/config/routes.rb +2 -1
- data/lib/que/view/dsl.rb +97 -9
- data/lib/que/view/version.rb +1 -1
- data/lib/que/view.rb +3 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9576dbcacaced63da0924a3315af1dede11887b6dcfdbca1029356691cd1dd02
|
4
|
+
data.tar.gz: abb8d73cfb96eda19ce45fe767edb91e57b9be595242c0a802503d0e16c3dc31
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e44bde7cb0ffd37a3f7ec82dd85639c961a5cf10aab179b75a7f1ea02edc5e432cd1f9655a204f6d16e6d3addeb9d50ffc79df5b8b51d8b01d335433f8d1587a
|
7
|
+
data.tar.gz: fe3ada013eff8f6660126c56975e68e663f5c85ab2cd32957c4306e0c419d2285156604262677e02039c289cb22cf0921ca5541781dbb7b2efed1feec186c60e
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Que::View
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
How to use my plugin.
|
2
|
+
Rails engine inspired by [Que::Web](https://github.com/statianzo/que-web) for [Que](https://github.com/que-rb/que) job queue.
|
3
|
+
SQL queries came from Que::Web, some styling from there too.
|
4
|
+
Benefits for using this one: independent from Sinatra (que-web based on Sinatra)
|
6
5
|
|
7
6
|
## Installation
|
7
|
+
|
8
8
|
Add this line to your application's Gemfile:
|
9
9
|
|
10
10
|
```ruby
|
@@ -17,13 +17,40 @@ And then execute:
|
|
17
17
|
$ bundle install
|
18
18
|
```
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
You can configure username/password for production web view.
|
23
|
+
Add this lines to config/initializers/que_view.rb
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
Que::View.configure do |config|
|
27
|
+
config.ui_username = 'username'
|
28
|
+
config.ui_password = 'password'
|
29
|
+
config.ui_secured_environments = ['production']
|
30
|
+
end
|
23
31
|
```
|
24
32
|
|
25
|
-
##
|
26
|
-
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
Add this line to config/routes.rb
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
mount Que::Web::Engine => '/que_web'
|
39
|
+
```
|
40
|
+
|
41
|
+
Add this line to assets/config/manifest.js
|
42
|
+
|
43
|
+
```js
|
44
|
+
//= link que/view/application.css
|
45
|
+
```
|
46
|
+
|
47
|
+
## TODO
|
48
|
+
|
49
|
+
- [X] rescheduling jobs
|
50
|
+
- [X] deleting jobs
|
51
|
+
- [ ] better styles for UI
|
52
|
+
- [ ] rendering running jobs
|
53
|
+
- [ ] tests
|
27
54
|
|
28
55
|
## License
|
29
56
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
@@ -24,24 +24,45 @@
|
|
24
24
|
display: flex;
|
25
25
|
flex-direction: row;
|
26
26
|
margin: 0 auto;
|
27
|
-
max-width:
|
27
|
+
max-width: 75rem;
|
28
28
|
width: 100%;
|
29
29
|
}
|
30
30
|
|
31
|
-
.row .column
|
31
|
+
.row .column {
|
32
32
|
flex: 1;
|
33
33
|
padding: 1rem;
|
34
34
|
}
|
35
35
|
|
36
|
+
.row table {
|
37
|
+
flex: 1;
|
38
|
+
margin-bottom: 1rem;
|
39
|
+
}
|
40
|
+
|
36
41
|
table th, table td {
|
37
42
|
padding: .25rem .75rem;
|
38
|
-
border-bottom: 1px solid #
|
43
|
+
border-bottom: 1px solid #BBB;
|
39
44
|
}
|
40
45
|
|
41
|
-
table
|
46
|
+
table th {
|
47
|
+
text-align: left;
|
48
|
+
}
|
49
|
+
|
50
|
+
table tbody tr:nth-of-type(2n), table tbody tr:hover {
|
42
51
|
background: #DDD;
|
43
52
|
}
|
44
53
|
|
54
|
+
table tbody tr:nth-of-type(2n):hover {
|
55
|
+
background: #CCC;
|
56
|
+
}
|
57
|
+
|
58
|
+
table p {
|
59
|
+
margin: 0;
|
60
|
+
}
|
61
|
+
|
62
|
+
.actions {
|
63
|
+
display: flex;
|
64
|
+
}
|
65
|
+
|
45
66
|
.dashboard-stat {
|
46
67
|
text-align: center;
|
47
68
|
display: table;
|
@@ -67,18 +88,14 @@ table tbody tr:nth-of-type(2n) {
|
|
67
88
|
margin: 0;
|
68
89
|
}
|
69
90
|
|
70
|
-
.dashboard-stat.
|
71
|
-
background: #
|
91
|
+
.dashboard-stat.running {
|
92
|
+
background: #CFD0C1;
|
72
93
|
}
|
73
94
|
|
74
95
|
.dashboard-stat.scheduled {
|
75
96
|
background: #828E8C;
|
76
97
|
}
|
77
98
|
|
78
|
-
.dashboard-stat.running {
|
79
|
-
background: #CFD0C1;
|
80
|
-
}
|
81
|
-
|
82
99
|
.dashboard-stat.failing {
|
83
100
|
background: #E8866C;
|
84
101
|
}
|
@@ -88,3 +105,12 @@ table tbody tr:nth-of-type(2n) {
|
|
88
105
|
line-height: 5rem;
|
89
106
|
color: black;
|
90
107
|
}
|
108
|
+
|
109
|
+
.btn-danger {
|
110
|
+
cursor: pointer;
|
111
|
+
border: none;
|
112
|
+
border-radius: .25rem;
|
113
|
+
background: #E8866C;
|
114
|
+
padding: .25rem .5rem;
|
115
|
+
margin-right: .5rem;
|
116
|
+
}
|
@@ -3,6 +3,20 @@
|
|
3
3
|
module Que
|
4
4
|
module View
|
5
5
|
class ApplicationController < ActionController::Base
|
6
|
+
http_basic_authenticate_with name: ::Que::View.configuration.ui_username,
|
7
|
+
password: ::Que::View.configuration.ui_password,
|
8
|
+
if: -> { basic_auth_enabled? }
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def basic_auth_enabled?
|
13
|
+
configuration = ::Que::View.configuration
|
14
|
+
|
15
|
+
return false if configuration.ui_username.blank?
|
16
|
+
return false if configuration.ui_password.blank?
|
17
|
+
|
18
|
+
configuration.ui_secured_environments.include?(Rails.env)
|
19
|
+
end
|
6
20
|
end
|
7
21
|
end
|
8
22
|
end
|
@@ -5,15 +5,36 @@ module Que
|
|
5
5
|
class JobsController < Que::View::ApplicationController
|
6
6
|
PER_PAGE = 20
|
7
7
|
|
8
|
+
before_action :find_job, only: %i[show]
|
9
|
+
|
8
10
|
def index
|
9
11
|
@jobs = find_jobs(params[:status])
|
10
12
|
@jobs_amount = find_jobs_amount(params[:status])
|
11
13
|
end
|
12
14
|
|
15
|
+
def show; end
|
16
|
+
|
17
|
+
def update
|
18
|
+
updated_rows = ::Que::View.reschedule_job(params[:id], Time.now)
|
19
|
+
redirect_to(
|
20
|
+
root_path,
|
21
|
+
notice: updated_rows.empty? ? 'Job is not rescheduled' : 'Job is rescheduled'
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
13
25
|
def destroy
|
26
|
+
updated_rows = ::Que::View.delete_job(params[:id])
|
27
|
+
redirect_to(
|
28
|
+
root_path,
|
29
|
+
notice: updated_rows.empty? ? 'Job is not deleted' : 'Job is deleted'
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def reschedule_all
|
34
|
+
updated_rows = reschedule_all_jobs(params[:status], Time.now)
|
14
35
|
redirect_to(
|
15
36
|
jobs_path(status: params[:status]),
|
16
|
-
notice: '
|
37
|
+
notice: updated_rows.empty? ? 'No jobs rescheduled' : "#{updated_rows.count} jobs rescheduled"
|
17
38
|
)
|
18
39
|
end
|
19
40
|
|
@@ -27,24 +48,54 @@ module Que
|
|
27
48
|
|
28
49
|
private
|
29
50
|
|
51
|
+
def find_job
|
52
|
+
@job = ::Que::View.fetch_job(params[:id])[0]
|
53
|
+
return if @job
|
54
|
+
|
55
|
+
redirect_to root_path, notice: 'Job is not found'
|
56
|
+
end
|
57
|
+
|
30
58
|
def find_jobs(status)
|
31
59
|
case status&.to_sym
|
32
|
-
when :
|
60
|
+
when :failed then ::Que::View.fetch_failed_jobs(PER_PAGE, offset, search)
|
61
|
+
when :scheduled then ::Que::View.fetch_scheduled_jobs(PER_PAGE, offset, search)
|
33
62
|
else []
|
34
63
|
end
|
35
64
|
end
|
36
65
|
|
37
66
|
def find_jobs_amount(status)
|
38
|
-
::Que::View.
|
67
|
+
::Que::View.fetch_dashboard_stats(search)[0][status&.to_sym]
|
68
|
+
end
|
69
|
+
|
70
|
+
def reschedule_all_jobs(status, time)
|
71
|
+
case status&.to_sym
|
72
|
+
when :failed then ::Que::View.reschedule_failed_jobs(time)
|
73
|
+
when :scheduled then ::Que::View.reschedule_scheduled_jobs(time)
|
74
|
+
else 0
|
75
|
+
end
|
39
76
|
end
|
40
77
|
|
41
78
|
def destroy_all_jobs(status)
|
42
79
|
case status&.to_sym
|
43
|
-
when :
|
80
|
+
when :failed then ::Que::View.delete_failed_jobs
|
81
|
+
when :scheduled then ::Que::View.delete_scheduled_jobs
|
44
82
|
else 0
|
45
83
|
end
|
46
84
|
end
|
47
85
|
|
86
|
+
def search
|
87
|
+
return '%' unless search_param
|
88
|
+
|
89
|
+
"%#{search_param}%"
|
90
|
+
end
|
91
|
+
|
92
|
+
def search_param
|
93
|
+
sanitised = (params[:search] || '').gsub(/[^0-9a-z:]/i, '')
|
94
|
+
return if sanitised.empty?
|
95
|
+
|
96
|
+
sanitised
|
97
|
+
end
|
98
|
+
|
48
99
|
def page
|
49
100
|
(params[:page] || 1).to_i
|
50
101
|
end
|
@@ -4,24 +4,41 @@
|
|
4
4
|
<thead>
|
5
5
|
<tr>
|
6
6
|
<th>ID</th>
|
7
|
-
<th>
|
7
|
+
<th>Run at</th>
|
8
8
|
<th>Job</th>
|
9
|
+
<th>Arguments</th>
|
9
10
|
<th>Queue</th>
|
10
|
-
|
11
|
-
|
11
|
+
<% if params[:status] == 'failing' %>
|
12
|
+
<th>Failures</th>
|
13
|
+
<th>Error</th>
|
14
|
+
<% end %>
|
15
|
+
<% if %w[failing scheduled].include?(params[:status]) %>
|
16
|
+
<th></th>
|
17
|
+
<% end %>
|
12
18
|
</tr>
|
13
19
|
</thead>
|
14
20
|
<tbody>
|
15
21
|
<% @jobs.each do |job| %>
|
16
22
|
<tr>
|
17
|
-
<td><%= job[:id] %></td>
|
18
|
-
<td><%= job[:
|
23
|
+
<td><%= link_to job[:id], job_path(job[:id]) %></td>
|
24
|
+
<td><%= job[:run_at].utc %></td>
|
19
25
|
<td><%= humanized_job_class(job) %></td>
|
20
26
|
<td><%= job[:queue] %></td>
|
21
|
-
<td><%= format_error(job) %></td>
|
22
27
|
<td>
|
23
|
-
|
28
|
+
<% job.dig(:args, 0, :arguments).each do |argument| %>
|
29
|
+
<p><%= argument %></p>
|
30
|
+
<% end %>
|
24
31
|
</td>
|
32
|
+
<% if params[:status] == 'failing' %>
|
33
|
+
<td><%= job[:error_count] %></td>
|
34
|
+
<td><%= format_error(job) %></td>
|
35
|
+
<% end %>
|
36
|
+
<% if %w[failing scheduled].include?(params[:status]) %>
|
37
|
+
<td class="actions">
|
38
|
+
<%= button_to 'Run', job_path(job[:id]), class: 'btn-danger', method: :patch, onclick: "return confirm('Are you sure you wish to reschedule job?')" %>
|
39
|
+
<%= button_to 'Delete', job_path(job[:id]), class: 'btn-danger', method: :delete, onclick: "return confirm('Are you sure you wish to delete job?')" %>
|
40
|
+
</td>
|
41
|
+
<% end %>
|
25
42
|
</tr>
|
26
43
|
<% end %>
|
27
44
|
</tbody>
|
@@ -30,6 +47,9 @@
|
|
30
47
|
<p>No jobs found</p>
|
31
48
|
<% end %>
|
32
49
|
</div>
|
33
|
-
<% if @jobs_amount.positive? %>
|
34
|
-
|
50
|
+
<% if %w[failing scheduled].include?(params[:status]) && @jobs_amount.positive? %>
|
51
|
+
<div class="row">
|
52
|
+
<%= button_to 'Run All', reschedule_all_jobs_path(status: params[:status]), class: 'btn-danger', method: :post, onclick: "return confirm('Are you sure you wish to reschedule all jobs?')" %>
|
53
|
+
<%= button_to 'Delete All', destroy_all_jobs_path(status: params[:status]), class: 'btn-danger', method: :delete, onclick: "return confirm('Are you sure you wish to delete all jobs?')" %>
|
54
|
+
</div>
|
35
55
|
<% end %>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="columns">
|
3
|
+
<h1>Job <%= @job[:id] %></h1>
|
4
|
+
</div>
|
5
|
+
</div>
|
6
|
+
<div class="row">
|
7
|
+
<table cellspacing="0">
|
8
|
+
<tbody>
|
9
|
+
<tr>
|
10
|
+
<th>Job</th>
|
11
|
+
<td><%= humanized_job_class(@job) %></td>
|
12
|
+
</tr>
|
13
|
+
<tr>
|
14
|
+
<th>Queue</th>
|
15
|
+
<td><%= @job[:queue] %></td>
|
16
|
+
</tr>
|
17
|
+
<tr>
|
18
|
+
<th>Priority</th>
|
19
|
+
<td><%= @job[:priority] %></td>
|
20
|
+
</tr>
|
21
|
+
<tr>
|
22
|
+
<th>Run at</th>
|
23
|
+
<td><%= @job[:run_at].utc %></td>
|
24
|
+
</tr>
|
25
|
+
<tr>
|
26
|
+
<th>Failures</th>
|
27
|
+
<td><%= @job[:error_count] %></td>
|
28
|
+
</tr>
|
29
|
+
<tr>
|
30
|
+
<th>Args</th>
|
31
|
+
<td>
|
32
|
+
<% @job.dig(:args, 0, :arguments).each do |argument| %>
|
33
|
+
<p><%= argument %></p>
|
34
|
+
<% end %>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<tr>
|
38
|
+
<th>Last Error</th>
|
39
|
+
<td>
|
40
|
+
<%= format_error(@job) %>
|
41
|
+
</td>
|
42
|
+
</tr>
|
43
|
+
</tbody>
|
44
|
+
</table>
|
45
|
+
</div>
|
46
|
+
<div class="row">
|
47
|
+
<div class="actions">
|
48
|
+
<%= button_to 'Run', job_path(@job[:id]), class: 'btn-danger', method: :patch, onclick: "return confirm('Are you sure you wish to reschedule job?')" %>
|
49
|
+
<%= button_to 'Delete', job_path(@job[:id]), class: 'btn-danger', method: :delete, onclick: "return confirm('Are you sure you wish to delete job?')" %>
|
50
|
+
</div>
|
51
|
+
</div>
|
@@ -1,22 +1,26 @@
|
|
1
1
|
<div class="row">
|
2
2
|
<div class="column">
|
3
3
|
<div class="dashboard-stat running">
|
4
|
-
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
<%= link_to jobs_path(status: 'running') do %>
|
5
|
+
<div class="cell">
|
6
|
+
<h2>Running</h2>
|
7
|
+
<span class="dashboard-value">
|
8
|
+
<%= @dashboard_stats[:running] %>
|
9
|
+
</span>
|
10
|
+
</div>
|
11
|
+
<% end %>
|
10
12
|
</div>
|
11
13
|
</div>
|
12
14
|
<div class="column">
|
13
15
|
<div class="dashboard-stat scheduled">
|
14
|
-
|
15
|
-
<
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
<%= link_to jobs_path(status: 'scheduled') do %>
|
17
|
+
<div class="cell">
|
18
|
+
<h2>Scheduled</h2>
|
19
|
+
<span class="dashboard-value">
|
20
|
+
<%= @dashboard_stats[:scheduled] %>
|
21
|
+
</span>
|
22
|
+
</div>
|
23
|
+
<% end %>
|
20
24
|
</div>
|
21
25
|
</div>
|
22
26
|
<div class="column">
|
data/config/routes.rb
CHANGED
data/lib/que/view/dsl.rb
CHANGED
@@ -2,23 +2,52 @@
|
|
2
2
|
|
3
3
|
module Que
|
4
4
|
module View
|
5
|
+
# rubocop: disable Metrics/ClassLength
|
5
6
|
class DSL
|
6
|
-
def
|
7
|
-
execute(
|
7
|
+
def fetch_dashboard_stats(...)
|
8
|
+
execute(fetch_dashboard_stats_sql(...))
|
8
9
|
end
|
9
10
|
|
10
|
-
def
|
11
|
-
execute(
|
11
|
+
def fetch_failing_jobs(...)
|
12
|
+
execute(fetch_failing_jobs_sql(...))
|
12
13
|
end
|
13
14
|
|
14
|
-
def
|
15
|
-
execute(
|
15
|
+
def fetch_scheduled_jobs(...)
|
16
|
+
execute(fetch_scheduled_jobs_sql(...))
|
17
|
+
end
|
18
|
+
|
19
|
+
def fetch_job(...)
|
20
|
+
execute(fetch_job_sql(...))
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete_failing_jobs
|
24
|
+
execute(delete_jobs_sql(lock_failing_jobs_sql))
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_scheduled_jobs
|
28
|
+
execute(delete_jobs_sql(lock_scheduled_jobs_sql))
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete_job(...)
|
32
|
+
execute(delete_jobs_sql(lock_job_sql(...)))
|
33
|
+
end
|
34
|
+
|
35
|
+
def reschedule_scheduled_jobs(time)
|
36
|
+
execute(reschedule_jobs_sql(lock_scheduled_jobs_sql, time))
|
37
|
+
end
|
38
|
+
|
39
|
+
def reschedule_failing_jobs(time)
|
40
|
+
execute(reschedule_jobs_sql(lock_failing_jobs_sql, time))
|
41
|
+
end
|
42
|
+
|
43
|
+
def reschedule_job(job_id, time)
|
44
|
+
execute(reschedule_jobs_sql(lock_job_sql(job_id), time))
|
16
45
|
end
|
17
46
|
|
18
47
|
private
|
19
48
|
|
20
49
|
# rubocop: disable Metrics/MethodLength
|
21
|
-
def
|
50
|
+
def fetch_dashboard_stats_sql(search)
|
22
51
|
<<-SQL.squish
|
23
52
|
SELECT count(*) AS total,
|
24
53
|
count(locks.job_id) AS running,
|
@@ -36,7 +65,7 @@ module Que
|
|
36
65
|
SQL
|
37
66
|
end
|
38
67
|
|
39
|
-
def
|
68
|
+
def fetch_failing_jobs_sql(per_page, offset, search)
|
40
69
|
<<-SQL.squish
|
41
70
|
SELECT que_jobs.*
|
42
71
|
FROM que_jobs
|
@@ -57,6 +86,36 @@ module Que
|
|
57
86
|
SQL
|
58
87
|
end
|
59
88
|
|
89
|
+
def fetch_scheduled_jobs_sql(per_page, offset, search)
|
90
|
+
<<-SQL.squish
|
91
|
+
SELECT que_jobs.*
|
92
|
+
FROM que_jobs
|
93
|
+
LEFT JOIN (
|
94
|
+
SELECT (classid::bigint << 32) + objid::bigint AS job_id
|
95
|
+
FROM pg_locks
|
96
|
+
WHERE locktype = 'advisory'
|
97
|
+
) locks ON (que_jobs.id=locks.job_id)
|
98
|
+
WHERE locks.job_id IS NULL
|
99
|
+
AND error_count = 0
|
100
|
+
AND (
|
101
|
+
job_class ILIKE ('#{search}')
|
102
|
+
OR que_jobs.args #>> '{0, job_class}' ILIKE ('#{search}')
|
103
|
+
)
|
104
|
+
ORDER BY run_at, id
|
105
|
+
LIMIT #{per_page}::int
|
106
|
+
OFFSET #{offset}::int
|
107
|
+
SQL
|
108
|
+
end
|
109
|
+
|
110
|
+
def fetch_job_sql(job_id)
|
111
|
+
<<-SQL.squish
|
112
|
+
SELECT *
|
113
|
+
FROM que_jobs
|
114
|
+
WHERE id = #{job_id}::bigint
|
115
|
+
LIMIT 1
|
116
|
+
SQL
|
117
|
+
end
|
118
|
+
|
60
119
|
def delete_jobs_sql(scope)
|
61
120
|
<<-SQL.squish
|
62
121
|
WITH target AS (#{scope})
|
@@ -68,18 +127,47 @@ module Que
|
|
68
127
|
SQL
|
69
128
|
end
|
70
129
|
|
71
|
-
def
|
130
|
+
def reschedule_jobs_sql(scope, time)
|
131
|
+
<<-SQL.squish
|
132
|
+
WITH target AS (#{scope})
|
133
|
+
UPDATE que_jobs
|
134
|
+
SET run_at = '#{time}'::timestamptz, expired_at = NULL
|
135
|
+
FROM target
|
136
|
+
WHERE target.locked
|
137
|
+
AND target.id = que_jobs.id
|
138
|
+
RETURNING pg_advisory_unlock(target.id)
|
139
|
+
SQL
|
140
|
+
end
|
141
|
+
|
142
|
+
def lock_failing_jobs_sql
|
72
143
|
<<-SQL.squish
|
73
144
|
SELECT id, pg_try_advisory_lock(id) AS locked
|
74
145
|
FROM que_jobs
|
75
146
|
WHERE error_count > 0
|
76
147
|
SQL
|
77
148
|
end
|
149
|
+
|
150
|
+
def lock_scheduled_jobs_sql
|
151
|
+
<<-SQL.squish
|
152
|
+
SELECT id, pg_try_advisory_lock(id) AS locked
|
153
|
+
FROM que_jobs
|
154
|
+
WHERE error_count = 0
|
155
|
+
SQL
|
156
|
+
end
|
157
|
+
|
158
|
+
def lock_job_sql(job_id)
|
159
|
+
<<-SQL.squish
|
160
|
+
SELECT id, pg_try_advisory_lock(id) AS locked
|
161
|
+
FROM que_jobs
|
162
|
+
WHERE id = #{job_id}::bigint
|
163
|
+
SQL
|
164
|
+
end
|
78
165
|
# rubocop: enable Metrics/MethodLength
|
79
166
|
|
80
167
|
def execute(sql)
|
81
168
|
Que.execute(sql)
|
82
169
|
end
|
83
170
|
end
|
171
|
+
# rubocop: enable Metrics/ClassLength
|
84
172
|
end
|
85
173
|
end
|
data/lib/que/view/version.rb
CHANGED
data/lib/que/view.rb
CHANGED
@@ -34,6 +34,8 @@ module Que
|
|
34
34
|
|
35
35
|
# Public: All the methods delegated to instance. These should match the interface of Que::View::DSL.
|
36
36
|
def_delegators :instance,
|
37
|
-
:
|
37
|
+
:fetch_dashboard_stats, :fetch_failing_jobs, :fetch_scheduled_jobs, :fetch_job,
|
38
|
+
:delete_failing_jobs, :delete_scheduled_jobs, :delete_job,
|
39
|
+
:reschedule_scheduled_jobs, :reschedule_failing_jobs, :reschedule_job
|
38
40
|
end
|
39
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: que-view
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bogdanov Anton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: que
|
@@ -168,6 +168,7 @@ files:
|
|
168
168
|
- app/helpers/que/view/application_helper.rb
|
169
169
|
- app/views/layouts/que/view/application.html.erb
|
170
170
|
- app/views/que/view/jobs/index.html.erb
|
171
|
+
- app/views/que/view/jobs/show.html.erb
|
171
172
|
- app/views/que/view/welcome/index.html.erb
|
172
173
|
- config/routes.rb
|
173
174
|
- lib/que/view.rb
|