good_job 3.3.3 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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