good_job 3.3.3 → 3.4.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/CHANGELOG.md +22 -3
- data/README.md +1 -1
- data/app/controllers/good_job/cron_entries_controller.rb +20 -0
- data/app/filters/good_job/base_filter.rb +8 -7
- data/app/filters/good_job/jobs_filter.rb +14 -13
- data/app/models/good_job/base_record.rb +10 -0
- data/app/models/good_job/cron_entry.rb +14 -0
- data/app/models/good_job/process.rb +1 -0
- data/app/models/good_job/setting.rb +30 -0
- data/app/views/good_job/cron_entries/index.html.erb +13 -3
- data/app/views/good_job/shared/_filter.erb +42 -40
- data/app/views/good_job/shared/icons/_pause.html.erb +4 -0
- data/config/routes.rb +2 -0
- data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +7 -0
- data/lib/generators/good_job/templates/update/migrations/02_create_good_job_settings.rb.erb +19 -0
- data/lib/good_job/configuration.rb +28 -0
- data/lib/good_job/cron_manager.rb +1 -1
- data/lib/good_job/version.rb +1 -1
- metadata +5 -3
- data/lib/good_job/enqueuing.rb +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 73efcb35d2a5e0ccfd13e2526a9a9d4a7195c4bf2e4a7f4127894a68c7f5dbb9
|
|
4
|
+
data.tar.gz: d9fddab346e5851e23daa5d9bef8c68b1fd5472f37d687c3cb49c5ff551cc31c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d720ab703536db9dfd396097aeb8b3aae64f5cd55a1754a9965eaaca275a2babfc4a05d249fb13896d776d02034553bd81cdda8b0af19a6f49d9a3a4bca29045
|
|
7
|
+
data.tar.gz: 9dd2af1f00637c3db171934777cc02be231e3ee98ad953aa9fcf030b00faa9fdd2b811f6e69094120a2deee8415e6a33d2d2a4a4d7701fbf89f7c45e272658ef
|
data/CHANGELOG.md
CHANGED
|
@@ -1,17 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [v3.
|
|
3
|
+
## [v3.4.0](https://github.com/bensheldon/good_job/tree/v3.4.0) (2022-08-05)
|
|
4
4
|
|
|
5
|
-
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.3.
|
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.3.3...v3.4.0)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- Add cron\_enabled attribute to good\_job and pass it to process current state [\#675](https://github.com/bensheldon/good_job/pull/675) ([saksham-jain](https://github.com/saksham-jain))
|
|
10
|
+
- Reverse Dashboard Filter Hierarchy to be: queues+jobs then state [\#666](https://github.com/bensheldon/good_job/pull/666) ([bensheldon](https://github.com/bensheldon))
|
|
11
|
+
- Allow cron entries to be temporarily disabled and re-enabled through the Dashboard [\#649](https://github.com/bensheldon/good_job/pull/649) ([alex-klepa](https://github.com/alex-klepa))
|
|
12
|
+
- Add Configuration.total\_estimated\_threads to report number of threads consumed by GoodJob [\#645](https://github.com/bensheldon/good_job/pull/645) ([bensheldon](https://github.com/bensheldon))
|
|
6
13
|
|
|
7
14
|
**Closed issues:**
|
|
8
15
|
|
|
9
|
-
-
|
|
16
|
+
- Cron Schedule jobs add disable action [\#540](https://github.com/bensheldon/good_job/issues/540)
|
|
10
17
|
|
|
11
18
|
**Merged pull requests:**
|
|
12
19
|
|
|
20
|
+
- Removed text that implied an existing feature had not been finished [\#688](https://github.com/bensheldon/good_job/pull/688) ([pgvsalamander](https://github.com/pgvsalamander))
|
|
21
|
+
|
|
22
|
+
## [v3.3.3](https://github.com/bensheldon/good_job/tree/v3.3.3) (2022-08-02)
|
|
23
|
+
|
|
24
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.3.2...v3.3.3)
|
|
25
|
+
|
|
26
|
+
**Fixed bugs:**
|
|
27
|
+
|
|
13
28
|
- Detect usage of `puma` CLI for async mode [\#686](https://github.com/bensheldon/good_job/pull/686) ([bensheldon](https://github.com/bensheldon))
|
|
14
29
|
|
|
30
|
+
**Closed issues:**
|
|
31
|
+
|
|
32
|
+
- Async not working Rails 7 with puma CLI [\#685](https://github.com/bensheldon/good_job/issues/685)
|
|
33
|
+
|
|
15
34
|
## [v3.3.2](https://github.com/bensheldon/good_job/tree/v3.3.2) (2022-07-27)
|
|
16
35
|
|
|
17
36
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.3.1...v3.3.2)
|
data/README.md
CHANGED
|
@@ -472,7 +472,7 @@ config.good_job.cron = {
|
|
|
472
472
|
args: [42, "life"], # positional arguments to pass; can also be a proc e.g. `-> { [Time.now] }`
|
|
473
473
|
kwargs: { name: "Alice" }, # keyword arguments to pass; can also be a proc e.g. `-> { { name: NAMES.sample } }`
|
|
474
474
|
set: { priority: -10 }, # additional ActiveJob properties; can also be a lambda/proc e.g. `-> { { priority: [1,2].sample } }`
|
|
475
|
-
description: "Something helpful", # optional description that appears in Dashboard
|
|
475
|
+
description: "Something helpful", # optional description that appears in Dashboard
|
|
476
476
|
},
|
|
477
477
|
another_task: {
|
|
478
478
|
cron: "0 0,12 * * *",
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module GoodJob
|
|
3
3
|
class CronEntriesController < GoodJob::ApplicationController
|
|
4
|
+
before_action :check_settings_migration!, only: [:enable, :disable]
|
|
5
|
+
|
|
4
6
|
def index
|
|
5
7
|
@cron_entries = CronEntry.all
|
|
6
8
|
end
|
|
@@ -15,5 +17,23 @@ module GoodJob
|
|
|
15
17
|
@cron_entry.enqueue(Time.current)
|
|
16
18
|
redirect_back(fallback_location: cron_entries_path, notice: "Cron entry has been enqueued.")
|
|
17
19
|
end
|
|
20
|
+
|
|
21
|
+
def enable
|
|
22
|
+
@cron_entry = CronEntry.find(params[:cron_key])
|
|
23
|
+
@cron_entry.enable
|
|
24
|
+
redirect_back(fallback_location: cron_entries_path, notice: "Cron entry has been enabled.")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def disable
|
|
28
|
+
@cron_entry = CronEntry.find(params[:cron_key])
|
|
29
|
+
@cron_entry.disable
|
|
30
|
+
redirect_back(fallback_location: cron_entries_path, notice: "Cron entry has been disabled.")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def check_settings_migration!
|
|
36
|
+
redirect_back(fallback_location: cron_entries_path, alert: "Requires pending GoodJob database migration.") unless GoodJob::Setting.migrated?
|
|
37
|
+
end
|
|
18
38
|
end
|
|
19
39
|
end
|
|
@@ -24,18 +24,19 @@ module GoodJob
|
|
|
24
24
|
@_last ||= records.last
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def job_classes
|
|
28
|
-
base_query.group("serialized_params->>'job_class'").count
|
|
29
|
-
.sort_by { |name, _count| name.to_s }
|
|
30
|
-
.to_h
|
|
31
|
-
end
|
|
32
|
-
|
|
33
27
|
def queues
|
|
34
28
|
base_query.group(:queue_name).count
|
|
35
29
|
.sort_by { |name, _count| name.to_s || EMPTY }
|
|
36
30
|
.to_h
|
|
37
31
|
end
|
|
38
32
|
|
|
33
|
+
def job_classes
|
|
34
|
+
filtered_query(params.slice(:queue_name)).unscope(:select)
|
|
35
|
+
.group("serialized_params->>'job_class'").count
|
|
36
|
+
.sort_by { |name, _count| name.to_s }
|
|
37
|
+
.to_h
|
|
38
|
+
end
|
|
39
|
+
|
|
39
40
|
def states
|
|
40
41
|
raise NotImplementedError
|
|
41
42
|
end
|
|
@@ -51,7 +52,7 @@ module GoodJob
|
|
|
51
52
|
}.merge(override).delete_if { |_, v| v.blank? }
|
|
52
53
|
end
|
|
53
54
|
|
|
54
|
-
def filtered_query
|
|
55
|
+
def filtered_query(filtered_params = params)
|
|
55
56
|
raise NotImplementedError
|
|
56
57
|
end
|
|
57
58
|
|
|
@@ -2,26 +2,27 @@
|
|
|
2
2
|
module GoodJob
|
|
3
3
|
class JobsFilter < BaseFilter
|
|
4
4
|
def states
|
|
5
|
+
query = filtered_query(params.except(:state)).unscope(:select)
|
|
5
6
|
{
|
|
6
|
-
'scheduled' =>
|
|
7
|
-
'retried' =>
|
|
8
|
-
'queued' =>
|
|
9
|
-
'running' =>
|
|
10
|
-
'finished' =>
|
|
11
|
-
'discarded' =>
|
|
7
|
+
'scheduled' => query.scheduled.count,
|
|
8
|
+
'retried' => query.retried.count,
|
|
9
|
+
'queued' => query.queued.count,
|
|
10
|
+
'running' => query.running.count,
|
|
11
|
+
'finished' => query.finished.count,
|
|
12
|
+
'discarded' => query.discarded.count,
|
|
12
13
|
}
|
|
13
14
|
end
|
|
14
15
|
|
|
15
|
-
def filtered_query
|
|
16
|
+
def filtered_query(filter_params = params)
|
|
16
17
|
query = base_query.includes(:executions).includes_advisory_locks
|
|
17
18
|
|
|
18
|
-
query = query.job_class(
|
|
19
|
-
query = query.where(queue_name:
|
|
20
|
-
query = query.search_text(
|
|
21
|
-
query = query.where(cron_key:
|
|
19
|
+
query = query.job_class(filter_params[:job_class]) if filter_params[:job_class].present?
|
|
20
|
+
query = query.where(queue_name: filter_params[:queue_name]) if filter_params[:queue_name].present?
|
|
21
|
+
query = query.search_text(filter_params[:query]) if filter_params[:query].present?
|
|
22
|
+
query = query.where(cron_key: filter_params[:cron_key]) if filter_params[:cron_key].present?
|
|
22
23
|
|
|
23
|
-
if
|
|
24
|
-
case
|
|
24
|
+
if filter_params[:state]
|
|
25
|
+
case filter_params[:state]
|
|
25
26
|
when 'discarded'
|
|
26
27
|
query = query.discarded
|
|
27
28
|
when 'finished'
|
|
@@ -16,5 +16,15 @@ module GoodJob
|
|
|
16
16
|
DEPRECATION
|
|
17
17
|
nil
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
# Checks for whether the schema is up to date.
|
|
21
|
+
# Can be overriden by child class.
|
|
22
|
+
# @return [Boolean]
|
|
23
|
+
def self.migrated?
|
|
24
|
+
return true if connection.table_exists?(table_name)
|
|
25
|
+
|
|
26
|
+
migration_pending_warning!
|
|
27
|
+
false
|
|
28
|
+
end
|
|
19
29
|
end
|
|
20
30
|
end
|
|
@@ -86,6 +86,20 @@ module GoodJob # :nodoc:
|
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
+
def enabled?
|
|
90
|
+
return true unless GoodJob::Setting.migrated?
|
|
91
|
+
|
|
92
|
+
GoodJob::Setting.cron_key_enabled?(key)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def enable
|
|
96
|
+
GoodJob::Setting.cron_key_enable(key)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def disable
|
|
100
|
+
GoodJob::Setting.cron_key_disable(key)
|
|
101
|
+
end
|
|
102
|
+
|
|
89
103
|
def enqueue(cron_at = nil)
|
|
90
104
|
GoodJob::CurrentThread.within do |current_thread|
|
|
91
105
|
current_thread.cron_key = key
|
|
@@ -48,6 +48,7 @@ module GoodJob # :nodoc:
|
|
|
48
48
|
preserve_job_records: GoodJob.preserve_job_records,
|
|
49
49
|
retry_on_unhandled_error: GoodJob.retry_on_unhandled_error,
|
|
50
50
|
schedulers: GoodJob::Scheduler.instances.map(&:name),
|
|
51
|
+
cron_enabled: GoodJob.configuration.enable_cron?,
|
|
51
52
|
}
|
|
52
53
|
end
|
|
53
54
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GoodJob
|
|
4
|
+
class Setting < BaseRecord
|
|
5
|
+
CRON_KEYS_DISABLED = "cron_keys_disabled"
|
|
6
|
+
|
|
7
|
+
self.table_name = 'good_job_settings'
|
|
8
|
+
|
|
9
|
+
def self.cron_key_enabled?(key)
|
|
10
|
+
cron_disabled = find_by(key: CRON_KEYS_DISABLED)&.value || []
|
|
11
|
+
cron_disabled.exclude?(key.to_s)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.cron_key_enable(key)
|
|
15
|
+
setting = GoodJob::Setting.find_by(key: CRON_KEYS_DISABLED)
|
|
16
|
+
return unless setting&.value&.include?(key.to_s)
|
|
17
|
+
|
|
18
|
+
setting.value.delete(key.to_s)
|
|
19
|
+
setting.save!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def self.cron_key_disable(key)
|
|
23
|
+
setting = find_or_initialize_by(key: CRON_KEYS_DISABLED) do |record|
|
|
24
|
+
record.value = []
|
|
25
|
+
end
|
|
26
|
+
setting.value << key
|
|
27
|
+
setting.save!
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -37,10 +37,20 @@
|
|
|
37
37
|
<% end %>
|
|
38
38
|
</div>
|
|
39
39
|
<div class="col d-flex gap-3 justify-content-end">
|
|
40
|
-
<%= button_to enqueue_cron_entry_path(cron_entry
|
|
41
|
-
<%=
|
|
42
|
-
Run Now
|
|
40
|
+
<%= button_to enqueue_cron_entry_path(cron_entry), method: :post, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Enqueue cron entry now" }, title: "Enqueue cron entry now", data: { confirm: "Confirm enqueue cron entry now" } do %>
|
|
41
|
+
<%= render_icon "skip_forward" %>
|
|
43
42
|
<% end %>
|
|
43
|
+
|
|
44
|
+
<% if cron_entry.enabled? %>
|
|
45
|
+
<%= button_to disable_cron_entry_path(cron_entry), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Disable cron entry" }, title: "Disable cron entry", data: { confirm: "Confirm disable cron entry" } do %>
|
|
46
|
+
<%= render_icon "pause" %>
|
|
47
|
+
<% end %>
|
|
48
|
+
<% else %>
|
|
49
|
+
<%= button_to enable_cron_entry_path(cron_entry), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Enable cron entry" }, title: "Enable cron entry", data: { confirm: "Confirm enable cron entry" } do %>
|
|
50
|
+
<%= render_icon "play" %>
|
|
51
|
+
<% end %>
|
|
52
|
+
<% end %>
|
|
53
|
+
|
|
44
54
|
<%= tag.button type: "button", class: "btn btn-sm text-muted", role: "button",
|
|
45
55
|
title: "Inspect",
|
|
46
56
|
data: { bs_toggle: "collapse", bs_target: "##{dom_id(cron_entry, 'properties')}" },
|
|
@@ -2,14 +2,53 @@
|
|
|
2
2
|
<div class="bg-light break-out">
|
|
3
3
|
<h2 class="container-fluid pt-3 pb-2"><%= title %></h2>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
<%= form_with(url: "", method: :get, local: true, id: "filter_form", class: "container-fluid") do |form| %>
|
|
6
|
+
<%= hidden_field_tag :poll, params[:poll] %>
|
|
7
|
+
<%= hidden_field_tag :state, params[:state] %>
|
|
8
|
+
<div class="d-flex flex-row w-100">
|
|
9
|
+
<div class="me-2">
|
|
10
|
+
<select name="queue_name" id="job_queue_filter" class="form-select form-select-sm">
|
|
11
|
+
<option value="" <%= "selected='selected'" if params[:queue_name].blank? %>>All queues</option>
|
|
12
|
+
|
|
13
|
+
<% filter.queues.each do |name, count| %>
|
|
14
|
+
<option value="<%= name.to_param %>" <%= "selected='selected'" if params[:queue_name] == name %>><%= name %> (<%= number_with_delimiter(count) %>)</option>
|
|
15
|
+
<% end %>
|
|
16
|
+
</select>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="me-2">
|
|
20
|
+
<select name="job_class" id="job_class_filter" class="form-select form-select-sm">
|
|
21
|
+
<option value="" <%= "selected='selected'" if params[:job_class].blank? %>>All jobs</option>
|
|
22
|
+
|
|
23
|
+
<% filter.job_classes.each do |name, count| %>
|
|
24
|
+
<option value="<%= name.to_param %>" <%= "selected='selected'" if params[:job_class] == name %>><%= name %> (<%= number_with_delimiter(count) %>)</option>
|
|
25
|
+
<% end %>
|
|
26
|
+
</select>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="me-2 flex-fill">
|
|
30
|
+
<%= search_field_tag "query", params[:query], class: "form-control form-control-sm", placeholder: "Search by class, job id, job params, and error text." %>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<div class="d-flex flex-col align-items-end">
|
|
34
|
+
<div>
|
|
35
|
+
<%= form.submit "Search", name: nil, class: "btn btn-primary btn-sm" %>
|
|
36
|
+
<%= link_to filter.to_params(job_class: nil, state: nil, queue_name: nil, query: nil), class: "btn btn-secondary btn-sm" do %>
|
|
37
|
+
Clear
|
|
38
|
+
<% end %>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
<% end %>
|
|
43
|
+
|
|
44
|
+
<ul class="nav nav-tabs bg-light px-3 my-3">
|
|
6
45
|
<li class="nav-item">
|
|
7
|
-
<%= link_to "All",
|
|
46
|
+
<%= link_to "All", filter.to_params(state: nil), class: "nav-link #{"active" unless params[:state].present?}" %>
|
|
8
47
|
</li>
|
|
9
48
|
|
|
10
49
|
<% filter.states.each do |name, count| %>
|
|
11
50
|
<li class="nav-item">
|
|
12
|
-
<%= link_to
|
|
51
|
+
<%= link_to filter.to_params(state: name), class: "nav-link #{"active" if params[:state] == name}" do %>
|
|
13
52
|
<%= t(name, scope: 'good_job.status') %>
|
|
14
53
|
<span class="badge bg-primary rounded-pill <%= "bg-secondary" if count == 0 %>"><%= number_with_delimiter(count) %></span>
|
|
15
54
|
<% end %>
|
|
@@ -18,43 +57,6 @@
|
|
|
18
57
|
</ul>
|
|
19
58
|
</div>
|
|
20
59
|
|
|
21
|
-
<%= form_with(url: "", method: :get, local: true, id: "filter_form", class: "container-fluid") do |form| %>
|
|
22
|
-
<%= hidden_field_tag :poll, params[:poll] %>
|
|
23
|
-
<%= hidden_field_tag :state, params[:state] %>
|
|
24
|
-
<div class="d-flex flex-row w-100">
|
|
25
|
-
<div class="me-2">
|
|
26
|
-
<select name="job_class" id="job_class_filter" class="form-select form-select-sm">
|
|
27
|
-
<option value="" <%= "selected='selected'" if params[:job_class].blank? %>>All jobs</option>
|
|
28
|
-
|
|
29
|
-
<% filter.job_classes.each do |name, count| %>
|
|
30
|
-
<option value="<%= name.to_param %>" <%= "selected='selected'" if params[:job_class] == name %>><%= name %> (<%= count %>)</option>
|
|
31
|
-
<% end %>
|
|
32
|
-
</select>
|
|
33
|
-
</div>
|
|
34
|
-
|
|
35
|
-
<div class="me-2">
|
|
36
|
-
<select name="queue_name" id="job_queue_filter" class="form-select form-select-sm">
|
|
37
|
-
<option value="" <%= "selected='selected'" if params[:queue_name].blank? %>>All queues</option>
|
|
38
|
-
|
|
39
|
-
<% filter.queues.each do |name, count| %>
|
|
40
|
-
<option value="<%= name.to_param %>" <%= "selected='selected'" if params[:queue_name] == name %>><%= name %> (<%= count %>)</option>
|
|
41
|
-
<% end %>
|
|
42
|
-
</select>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
<div class="me-2 flex-fill">
|
|
46
|
-
<%= search_field_tag "query", params[:query], class: "form-control form-control-sm", placeholder: "Search by class, job id, job params, and error text." %>
|
|
47
|
-
</div>
|
|
48
|
-
|
|
49
|
-
<div class="d-flex flex-col align-items-end">
|
|
50
|
-
<div>
|
|
51
|
-
<%= form.submit "Search", name: nil, class: "btn btn-primary btn-sm" %>
|
|
52
|
-
<%= link_to "Clear all", filter.to_params(job_class: nil, state: nil, queue_name: nil, query: nil), class: "btn btn-secondary btn-sm" %>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
</div>
|
|
56
|
-
<% end %>
|
|
57
|
-
|
|
58
60
|
<%= javascript_tag nonce: true do %>
|
|
59
61
|
document.addEventListener("DOMContentLoaded", () => {
|
|
60
62
|
document.querySelectorAll("#job_class_filter, #job_queue_filter").forEach((filter) => {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<!-- https://icons.getbootstrap.com/icons/pause-btn/ -->
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pause" viewBox="0 0 16 16">
|
|
3
|
+
<path d="M6 3.5a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5zm4 0a.5.5 0 0 1 .5.5v8a.5.5 0 0 1-1 0V4a.5.5 0 0 1 .5-.5z" />
|
|
4
|
+
</svg>
|
data/config/routes.rb
CHANGED
|
@@ -26,6 +26,13 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
|
|
26
26
|
t.jsonb :state
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
+
create_table :good_job_settings, id: :uuid do |t|
|
|
30
|
+
t.timestamps
|
|
31
|
+
t.text :key
|
|
32
|
+
t.jsonb :value
|
|
33
|
+
t.index :key, unique: true
|
|
34
|
+
end
|
|
35
|
+
|
|
29
36
|
add_index :good_jobs, :scheduled_at, where: "(finished_at IS NULL)", name: "index_good_jobs_on_scheduled_at"
|
|
30
37
|
add_index :good_jobs, [:queue_name, :scheduled_at], where: "(finished_at IS NULL)", name: :index_good_jobs_on_queue_name_and_scheduled_at
|
|
31
38
|
add_index :good_jobs, [:active_job_id, :created_at], name: :index_good_jobs_on_active_job_id_and_created_at
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
class CreateGoodJobSettings < ActiveRecord::Migration<%= migration_version %>
|
|
3
|
+
def change
|
|
4
|
+
reversible do |dir|
|
|
5
|
+
dir.up do
|
|
6
|
+
# Ensure this incremental update migration is idempotent
|
|
7
|
+
# with monolithic install migration.
|
|
8
|
+
return if connection.table_exists?(:good_job_settings)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
create_table :good_job_settings, id: :uuid do |t|
|
|
13
|
+
t.timestamps
|
|
14
|
+
t.text :key
|
|
15
|
+
t.jsonb :value
|
|
16
|
+
t.index :key, unique: true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -42,6 +42,34 @@ module GoodJob
|
|
|
42
42
|
# @return [Hash]
|
|
43
43
|
attr_reader :env
|
|
44
44
|
|
|
45
|
+
# Returns the maximum number of threads GoodJob might consume
|
|
46
|
+
# @param warn [Boolean] whether to print a warning when over the limit
|
|
47
|
+
# @return [Integer]
|
|
48
|
+
def self.total_estimated_threads(warn: false)
|
|
49
|
+
configuration = new({})
|
|
50
|
+
|
|
51
|
+
cron_threads = configuration.enable_cron? ? 2 : 0
|
|
52
|
+
notifier_threads = 1
|
|
53
|
+
scheduler_threads = GoodJob::Scheduler.instances.sum { |scheduler| scheduler.stats[:max_threads] }
|
|
54
|
+
|
|
55
|
+
good_job_threads = cron_threads + notifier_threads + scheduler_threads
|
|
56
|
+
puma_threads = (Puma::Server.current&.max_threads if defined?(Puma::Server)) || 0
|
|
57
|
+
|
|
58
|
+
total_threads = good_job_threads + puma_threads
|
|
59
|
+
activerecord_pool_size = ActiveRecord::Base.connection_pool&.size
|
|
60
|
+
|
|
61
|
+
if warn && activerecord_pool_size && total_threads > activerecord_pool_size
|
|
62
|
+
message = "GoodJob is using #{good_job_threads} threads, " \
|
|
63
|
+
"#{" and Puma is using #{puma_threads} threads, " if puma_threads.positive?}" \
|
|
64
|
+
"which is #{total_threads - activerecord_pool_size} thread(s) more than ActiveRecord's database connection pool size of #{activerecord_pool_size}. " \
|
|
65
|
+
"Consider increasing ActiveRecord's database connection pool size in config/database.yml."
|
|
66
|
+
|
|
67
|
+
GoodJob.logger.warn message
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
good_job_threads
|
|
71
|
+
end
|
|
72
|
+
|
|
45
73
|
# @param options [Hash] Any explicitly specified configuration options to
|
|
46
74
|
# use. Keys are symbols that match the various methods on this class.
|
|
47
75
|
# @param env [Hash] A +Hash+ from which to read environment variables that
|
data/lib/good_job/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: good_job
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ben Sheldon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-08-
|
|
11
|
+
date: 2022-08-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activejob
|
|
@@ -379,6 +379,7 @@ files:
|
|
|
379
379
|
- app/models/good_job/job.rb
|
|
380
380
|
- app/models/good_job/lockable.rb
|
|
381
381
|
- app/models/good_job/process.rb
|
|
382
|
+
- app/models/good_job/setting.rb
|
|
382
383
|
- app/views/good_job/cron_entries/index.html.erb
|
|
383
384
|
- app/views/good_job/cron_entries/show.html.erb
|
|
384
385
|
- app/views/good_job/jobs/_executions.erb
|
|
@@ -398,6 +399,7 @@ files:
|
|
|
398
399
|
- app/views/good_job/shared/icons/_dots.html.erb
|
|
399
400
|
- app/views/good_job/shared/icons/_exclamation.html.erb
|
|
400
401
|
- app/views/good_job/shared/icons/_info.html.erb
|
|
402
|
+
- app/views/good_job/shared/icons/_pause.html.erb
|
|
401
403
|
- app/views/good_job/shared/icons/_play.html.erb
|
|
402
404
|
- app/views/good_job/shared/icons/_skip_forward.html.erb
|
|
403
405
|
- app/views/good_job/shared/icons/_stop.html.erb
|
|
@@ -413,6 +415,7 @@ files:
|
|
|
413
415
|
- lib/generators/good_job/install_generator.rb
|
|
414
416
|
- lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb
|
|
415
417
|
- lib/generators/good_job/templates/update/migrations/01_create_good_jobs.rb.erb
|
|
418
|
+
- lib/generators/good_job/templates/update/migrations/02_create_good_job_settings.rb.erb
|
|
416
419
|
- lib/generators/good_job/update_generator.rb
|
|
417
420
|
- lib/good_job.rb
|
|
418
421
|
- lib/good_job/active_job_extensions/concurrency.rb
|
|
@@ -426,7 +429,6 @@ files:
|
|
|
426
429
|
- lib/good_job/daemon.rb
|
|
427
430
|
- lib/good_job/dependencies.rb
|
|
428
431
|
- lib/good_job/engine.rb
|
|
429
|
-
- lib/good_job/enqueuing.rb
|
|
430
432
|
- lib/good_job/job_performer.rb
|
|
431
433
|
- lib/good_job/log_subscriber.rb
|
|
432
434
|
- lib/good_job/multi_scheduler.rb
|
data/lib/good_job/enqueuing.rb
DELETED