good_job 4.14.0 → 4.14.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5eb23908b9969829cfe7d7eec72e7cb9eaac26ee20786e5778c291fccf768532
4
- data.tar.gz: 0b49c31b04c2d1b9c447a25ddaa74ca13a6434c984a79e1b47204bdf8f15192a
3
+ metadata.gz: af515dffcbbdb5c6f3e02ec7a1426b7d59aea355b33791c81cc20d043bcab7f4
4
+ data.tar.gz: e44f93e479b483af4c3848c7957df934198fb780260c3008c427ff864c3d67a8
5
5
  SHA512:
6
- metadata.gz: d05ad24c88ef9f7a396b8f3f6a966c5683eb3b984ad853075c11368dd4d9412264e33e76da8cbe62f207dd05fbfc265dbf5c3f20b3c80a4c031a12f44c3126ba
7
- data.tar.gz: 0e30892a4f9ad554c15ab7be7c11c2e04f5f87f49963826a4d4e21188b79e5b7b6d89ac9c06906793c259b4ca792aee8072d927efd135cc5a5f81fa6abff2a13
6
+ metadata.gz: 812281e391af58a897dd119e875be51c7569eaefa021f7fc05d42d69b185819c4077c04e8f40d23c3cf498862e04f8f9285fe9a29931a1d9bba4f1a61650ca37
7
+ data.tar.gz: 1941b6294d3339c590e2c37188a2f1568a3c32bc5e1f9cb2a76f0c58b94cce6781797d3d86853111a842f435adb8262611eca426dc16001bb6bc1b0a8437bde4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [v4.14.1](https://github.com/bensheldon/good_job/tree/v4.14.1) (2026-04-03)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.14.0...v4.14.1)
6
+
7
+ **Fixed bugs:**
8
+
9
+ - Fix N+1 queries on cron entries dashboard index page [\#1727](https://github.com/bensheldon/good_job/pull/1727) ([clinejj](https://github.com/clinejj))
10
+
3
11
  ## [v4.14.0](https://github.com/bensheldon/good_job/tree/v4.14.0) (2026-03-31)
4
12
 
5
13
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.13.3...v4.14.0)
@@ -4,6 +4,10 @@ module GoodJob
4
4
  class CronEntriesController < GoodJob::ApplicationController
5
5
  def index
6
6
  @cron_entries = CronEntry.all
7
+ @last_jobs = CronEntry.last_jobs_by_key(@cron_entries)
8
+ @enabled_states = GoodJob::Setting.cron_keys_enabled(
9
+ @cron_entries.map { |entry| [entry.key, entry.enabled_by_default?] }
10
+ )
7
11
  end
8
12
 
9
13
  def show
@@ -18,6 +18,30 @@ module GoodJob # :nodoc:
18
18
  configuration.cron_entries
19
19
  end
20
20
 
21
+ def self.last_jobs_by_key(cron_entries)
22
+ cron_keys = cron_entries.map { |entry| entry.key.to_s }
23
+ return {} if cron_keys.empty?
24
+
25
+ from_clause = GoodJob::Job.sanitize_sql_array(
26
+ ["unnest(ARRAY[?]::text[]) AS cron_keys(cron_key)", cron_keys]
27
+ )
28
+
29
+ join_clause = <<~SQL.squish
30
+ CROSS JOIN LATERAL (
31
+ SELECT * FROM good_jobs
32
+ WHERE good_jobs.cron_key = cron_keys.cron_key
33
+ ORDER BY cron_at DESC NULLS LAST
34
+ LIMIT 1
35
+ ) AS lateral_jobs
36
+ SQL
37
+
38
+ GoodJob::Job
39
+ .select("lateral_jobs.*")
40
+ .from(from_clause)
41
+ .joins(join_clause)
42
+ .index_by(&:cron_key)
43
+ end
44
+
21
45
  def self.find(key, configuration: nil)
22
46
  all(configuration: configuration).find { |entry| entry.key == key.to_sym }.tap do |cron_entry|
23
47
  raise ActiveRecord::RecordNotFound unless cron_entry
@@ -144,13 +168,13 @@ module GoodJob # :nodoc:
144
168
  (last_job.cron_at || last_job.created_at).localtime
145
169
  end
146
170
 
147
- private
148
-
149
171
  def enabled_by_default?
150
172
  value = params.fetch(:enabled_by_default, true)
151
173
  value.respond_to?(:call) ? value.call : value
152
174
  end
153
175
 
176
+ private
177
+
154
178
  def cron
155
179
  params.fetch(:cron)
156
180
  end
@@ -19,6 +19,16 @@ module GoodJob
19
19
  end
20
20
  end
21
21
 
22
+ def self.cron_keys_enabled(keys_with_defaults)
23
+ cron_disabled = find_by(key: CRON_KEYS_DISABLED)&.value || []
24
+ cron_enabled = find_by(key: CRON_KEYS_ENABLED)&.value || []
25
+
26
+ keys_with_defaults.to_h do |key, default|
27
+ key_s = key.to_s
28
+ [key_s, default ? cron_disabled.exclude?(key_s) : cron_enabled.include?(key_s)]
29
+ end
30
+ end
31
+
22
32
  def self.cron_key_enable(key)
23
33
  key_string = key.to_s
24
34
  enabled_setting = find_or_initialize_by(key: CRON_KEYS_ENABLED) do |record|
@@ -39,14 +39,16 @@
39
39
  <%= relative_time cron_entry.next_at %>
40
40
  </div>
41
41
  <div class="col-6 col-lg-1 text-wrap small">
42
- <% if cron_entry.last_job.present? %>
42
+ <% last_job = @last_jobs[cron_entry.key.to_s] %>
43
+ <% if last_job.present? %>
44
+ <% last_job_at = (last_job.cron_at || last_job.created_at).localtime %>
43
45
  <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.cron.last_run" %></div>
44
- <%= link_to relative_time(cron_entry.last_job_at), cron_entry_path(cron_entry), title: "Job #{cron_entry.last_job.id}" %>
46
+ <%= link_to relative_time(last_job_at), cron_entry_path(cron_entry), title: "Job #{last_job.id}" %>
45
47
  <% end %>
46
48
  </div>
47
49
  <div class="col-6 col-lg-1 text-wrap small">
48
50
  <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.cron.status" %></div>
49
- <% if cron_entry.enabled? %>
51
+ <% if @enabled_states[cron_entry.key.to_s] %>
50
52
  <span class="text-success"><%= t "good_job.models.cron.states.active" %></span>
51
53
  <% else %>
52
54
  <span class="text-muted"><%= t "good_job.models.cron.states.paused" %></span>
@@ -57,7 +59,7 @@
57
59
  <%= render_icon "skip_forward" %>
58
60
  <% end %>
59
61
 
60
- <% if cron_entry.enabled? %>
62
+ <% if @enabled_states[cron_entry.key.to_s] %>
61
63
  <%= button_to disable_cron_entry_path(cron_entry), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.cron_entries.actions.disable") }, title: t("good_job.cron_entries.actions.disable"), data: { turbo_confirm: t("good_job.cron_entries.actions.confirm_disable") } do %>
62
64
  <%= render_icon "pause" %>
63
65
  <% end %>
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GoodJob
4
4
  # GoodJob gem version.
5
- VERSION = '4.14.0'
5
+ VERSION = '4.14.1'
6
6
 
7
7
  # GoodJob version as Gem::Version object
8
8
  GEM_VERSION = Gem::Version.new(VERSION)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.14.0
4
+ version: 4.14.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon