que-view 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: 38f9f8ac4b062389e01cec98fee2320a8c8e59f29d8edd86aa2be02cec38e1af
|
4
|
+
data.tar.gz: 1768c7efe2e99b73707f1fa869ea30e36b988423193dad3ddd92754cf5831099
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3e47f14f62dfad432f2a172199c32635f1095770bcf81184845848f3464e2e414b5640db774cd35ba800dbe873ecdddb7530e56128a8697b32c7b63c15a9681
|
7
|
+
data.tar.gz: 15f29072e2fc6d31b8b675f52c1210821645f3180e1190b0d48b918a949f6a2dae61f1102afe59c84f800e792f06dc194b196c0c5a7e571ed684e968919e1e4f
|
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::Web.configuration.ui_username,
|
7
|
+
password: ::Que::Web.configuration.ui_password,
|
8
|
+
if: -> { basic_auth_enabled? }
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def basic_auth_enabled?
|
13
|
+
configuration = ::Que::Web.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.
|
4
|
+
version: 0.2.0
|
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
|