good_job 3.28.0 → 3.28.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: b22f482dcf118c82d0b5889c6c37fd72bb65ff9a010f4fcc486bc2f0c4fc0bbe
4
- data.tar.gz: 83b1d597eee0f0c9c37b4afdf82f96e2164bef2d3b27181c10678327803f718e
3
+ metadata.gz: 3bbf6aa5c2cdbc7b2ff5b5f7dd31a219140934b799737c192aa8de55e5030bca
4
+ data.tar.gz: 1f7c614722781287cf6482af08fe97d4af5305fdfbd7583ce343277b7b8fe5a1
5
5
  SHA512:
6
- metadata.gz: b0b84290323a36b818cf92763e9df745737099f3990c934914e8ae700d6cb3a2ceb237764a8ff24fe923d5a8af0d18394e14a6aec516085a2bf057579341747e
7
- data.tar.gz: 030e271e5218499dbbce39e21803a5da6ede65422addb33ba5a0024582ac0996418471664061ce54700b1e9a5819eeeac517c479bb79d329577985e148752811
6
+ metadata.gz: 3f97f043eed52700808203c42ab9a714a7fdefdd33f3a201045a9a1649e675de6305386439f4707788a89842993902187c21b89939e4458e6a1750d25d6972d1
7
+ data.tar.gz: a3591c147f153964a0d929d8b49c43386b9f03bf53414471eed55d5312d9bb72e0fbd0ee49b966519570b4a13f33d4fa5ddda91c47d6fa31342af928cfa8185a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+ ## [v3.28.1](https://github.com/bensheldon/good_job/tree/v3.28.1) (2024-04-24)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.28.0...v3.28.1)
6
+
7
+ **Fixed bugs:**
8
+
9
+ - Ensure job context does not leak into extensions when`perform_now` is called within another job [\#1336](https://github.com/bensheldon/good_job/pull/1336) ([bensheldon](https://github.com/bensheldon))
10
+
11
+ **Closed issues:**
12
+
13
+ - Executing perform\_now on a good\_job with GoodJobs::ActiveJobExtensions::Concurrency can run twice [\#1335](https://github.com/bensheldon/good_job/issues/1335)
14
+ - `erb_lint` doesn't lint all files [\#1329](https://github.com/bensheldon/good_job/issues/1329)
15
+ - Server hangs after \#1297 [\#1301](https://github.com/bensheldon/good_job/issues/1301)
16
+ - Figure out how to use bind parameters for time queries [\#1285](https://github.com/bensheldon/good_job/issues/1285)
17
+
18
+ **Merged pull requests:**
19
+
20
+ - Upgrade development / demo Ruby to v3.3.1 [\#1333](https://github.com/bensheldon/good_job/pull/1333) ([bensheldon](https://github.com/bensheldon))
21
+ - Exploratory testing for presence of scheduled\_at when enqueuing [\#1332](https://github.com/bensheldon/good_job/pull/1332) ([bensheldon](https://github.com/bensheldon))
22
+ - Run `erb_lint` against all the views and partials [\#1331](https://github.com/bensheldon/good_job/pull/1331) ([bensheldon](https://github.com/bensheldon))
23
+
3
24
  ## [v3.28.0](https://github.com/bensheldon/good_job/tree/v3.28.0) (2024-04-19)
4
25
 
5
26
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.27.4...v3.28.0)
@@ -2,14 +2,14 @@
2
2
  <div class="list-group list-group-flush text-nowrap table-jobs" role="table">
3
3
  <header class="list-group-item bg-body-tertiary">
4
4
  <div class="row small text-muted text-uppercase align-items-center">
5
- <div class="col-4"><%=t "good_job.models.batch.jobs" %></div>
6
- <div class="d-none d-lg-block col-lg-1 text-lg-center"><%=t "good_job.models.job.queue" %></div>
7
- <div class="d-none d-lg-block col-lg-1 text-lg-end"><%=t "good_job.models.job.priority" %></div>
8
- <div class="d-none d-lg-block col-lg-1 text-lg-end"><%=t "good_job.models.job.attempts" %></div>
5
+ <div class="col-4"><%= t("good_job.models.batch.jobs") %></div>
6
+ <div class="d-none d-lg-block col-lg-1 text-lg-center"><%= t "good_job.models.job.queue" %></div>
7
+ <div class="d-none d-lg-block col-lg-1 text-lg-end"><%= t "good_job.models.job.priority" %></div>
8
+ <div class="d-none d-lg-block col-lg-1 text-lg-end"><%= t "good_job.models.job.attempts" %></div>
9
9
  <div class="col text-end">
10
10
  <%= tag.button type: "button", class: "btn btn-sm text-muted", role: "button",
11
11
  data: { bs_toggle: "collapse", bs_target: ".job-params" },
12
- aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, "params")}" }.join(" ") } do %>
12
+ aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, 'params')}" }.join(" ") } do %>
13
13
  <%= render_icon "info" %>
14
14
  <span class="visually-hidden">Inspect</span>
15
15
  <% end %>
@@ -26,22 +26,24 @@
26
26
  <%= tag.h5 tag.code(link_to(job.display_name, job_path(job), class: "text-reset text-decoration-none")), class: "text-reset mb-0" %>
27
27
  </div>
28
28
  <div class="col-4 col-lg-1 text-lg-center">
29
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.job.queue" %></div>
29
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.job.queue" %></div>
30
30
  <span class="badge bg-primary text-dark font-monospace"><%= job.queue_name %></span>
31
31
  </div>
32
32
  <div class="col-4 col-lg-1 text-lg-end">
33
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.job.priority" %>Priority</div>
33
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.job.priority" %>Priority</div>
34
34
  <span class="font-monospace fw-bold"><%= job.priority %></span>
35
35
  </div>
36
36
  <div class="col-4 col-lg-1 text-lg-end">
37
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.job.attempts" %></div>
37
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.job.attempts" %></div>
38
38
  <% if job.executions_count > 0 && job.status != :finished %>
39
- <%= tag.span job.executions_count, class: "badge rounded-pill bg-danger", data: {
40
- bs_toggle: "popover",
41
- bs_trigger: "hover focus click",
42
- bs_placement: "bottom",
43
- bs_content: job.recent_error
44
- } %>
39
+ <%= tag.span job.executions_count, class: "badge rounded-pill bg-danger",
40
+ data: {
41
+ bs_toggle: "popover",
42
+ bs_trigger: "hover focus click",
43
+ bs_placement: "bottom",
44
+ bs_content: job.recent_error,
45
+ }
46
+ %>
45
47
  <% else %>
46
48
  <span class="badge bg-secondary rounded-pill"><%= job.executions_count %></span>
47
49
  <% end %>
@@ -53,33 +55,33 @@
53
55
  <div class="dropdown float-end">
54
56
  <button class="d-flex align-items-center btn btn-sm" type="button" id="<%= dom_id(job, :actions) %>" data-bs-toggle="dropdown" aria-expanded="false">
55
57
  <%= render_icon :dots %>
56
- <span class="visually-hidden"><%=t ".actions.title" %></span>
58
+ <span class="visually-hidden"><%= t ".actions.title" %></span>
57
59
  </button>
58
60
  <ul class="dropdown-menu shadow" aria-labelledby="<%= dom_id(job, :actions) %>">
59
61
  <li>
60
62
  <% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %>
61
63
  <%= link_to reschedule_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_reschedulable}", title: t(".actions.reschedule"), data: { confirm: t(".actions.confirm_reschedule"), disable: true } do %>
62
64
  <%= render_icon "skip_forward" %>
63
- <%=t "good_job.actions.reschedule" %>
65
+ <%= t "good_job.actions.reschedule" %>
64
66
  <% end %>
65
67
  </li>
66
68
  <li>
67
69
  <% job_discardable = job.status.in? [:scheduled, :retried, :queued] %>
68
70
  <%= link_to discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: t(".actions.discard"), data: { confirm: t(".actions.confirm_discard"), disable: true } do %>
69
71
  <%= render_icon "stop" %>
70
- <%=t "good_job.actions.discard" %>
72
+ <%= t "good_job.actions.discard" %>
71
73
  <% end %>
72
74
  </li>
73
75
  <li>
74
76
  <%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t(".actions.retry"), data: { confirm: t(".actions.confirm_retry"), disable: true } do %>
75
77
  <%= render_icon "arrow_clockwise" %>
76
- <%=t "good_job.actions.retry" %>
78
+ <%= t "good_job.actions.retry" %>
77
79
  <% end %>
78
80
  </li>
79
81
  <li>
80
82
  <%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :finished]}", title: t(".actions.destroy"), data: { confirm: t(".actions.confirm_destroy"), disable: true } do %>
81
83
  <%= render_icon "trash" %>
82
- <%=t "good_job.actions.destroy" %>
84
+ <%= t "good_job.actions.destroy" %>
83
85
  <% end %>
84
86
  </li>
85
87
 
@@ -89,7 +91,7 @@
89
91
  data: { bs_toggle: "collapse" },
90
92
  aria: { expanded: false, controls: dom_id(job, "params") } do %>
91
93
  <%= render_icon "info" %>
92
- <%=t "good_job.actions.inspect" %>
94
+ <%= t "good_job.actions.inspect" %>
93
95
  <% end %>
94
96
  </li>
95
97
  </ul>
@@ -103,7 +105,7 @@
103
105
  <% end %>
104
106
  <% else %>
105
107
  <div class="list-group-item py-4 text-center text-muted">
106
- <%=t ".no_jobs_found" %>
108
+ <%= t ".no_jobs_found" %>
107
109
  </div>
108
110
  <% end %>
109
111
  </div>
@@ -2,18 +2,18 @@
2
2
  <div class="list-group list-group-flush text-nowrap table-batches" role="table">
3
3
  <header class="list-group-item bg-body-tertiary">
4
4
  <div class="row small text-muted text-uppercase align-items-center">
5
- <div class="col-4"><%=t "good_job.models.batch.name" %></div>
6
- <div class="col-lg-1 d-none d-lg-block"><%=t "good_job.models.batch.created" %></div>
7
- <div class="col-lg-1 d-none d-lg-block"><%=t "good_job.models.batch.enqueued" %></div>
8
- <div class="col-lg-1 d-none d-lg-block"><%=t "good_job.models.batch.discarded" %></div>
9
- <div class="col-lg-1 d-none d-lg-block"><%=t "good_job.models.batch.finished" %></div>
10
- <div class="col-lg-1 d-none d-lg-block"><%=t "good_job.models.batch.jobs" %></div>
5
+ <div class="col-4"><%= t "good_job.models.batch.name" %></div>
6
+ <div class="col-lg-1 d-none d-lg-block"><%= t "good_job.models.batch.created" %></div>
7
+ <div class="col-lg-1 d-none d-lg-block"><%= t "good_job.models.batch.enqueued" %></div>
8
+ <div class="col-lg-1 d-none d-lg-block"><%= t "good_job.models.batch.discarded" %></div>
9
+ <div class="col-lg-1 d-none d-lg-block"><%= t "good_job.models.batch.finished" %></div>
10
+ <div class="col-lg-1 d-none d-lg-block"><%= t "good_job.models.batch.jobs" %></div>
11
11
  <div class="col text-end">
12
12
  <%= tag.button type: "button", class: "btn btn-sm text-muted", role: "button",
13
13
  data: { bs_toggle: "collapse", bs_target: ".batch-properties" },
14
- aria: { expanded: false, controls: batches.map { |batch| "##{dom_id(batch, "params")}" }.join(" ") } do %>
14
+ aria: { expanded: false, controls: batches.map { |batch| "##{dom_id(batch, 'params')}" }.join(" ") } do %>
15
15
  <%= render_icon "info" %>
16
- <span class="visually-hidden"><%=t "good_job.actions.inspect" %></span>
16
+ <span class="visually-hidden"><%= t "good_job.actions.inspect" %></span>
17
17
  <% end %>
18
18
  </div>
19
19
  </div>
@@ -33,29 +33,29 @@
33
33
  <% end %>
34
34
  </div>
35
35
  <div class="col-6 col-lg-1 text-wrap">
36
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.batch.created_at" %></div>
36
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.batch.created_at" %></div>
37
37
  <%= relative_time(batch.created_at) %>
38
38
  </div>
39
39
  <div class="col-6 col-lg-1 text-wrap">
40
40
  <% if batch.enqueued_at %>
41
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.batch.enqueued_at" %></div>
41
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.batch.enqueued_at" %></div>
42
42
  <%= relative_time(batch.enqueued_at) %>
43
43
  <% end %>
44
44
  </div>
45
45
  <div class="col-6 col-lg-1 text-wrap">
46
46
  <% if batch.discarded_at %>
47
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.batch.discarded_at" %></div>
47
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.batch.discarded_at" %></div>
48
48
  <%= relative_time(batch.discarded_at) %>
49
49
  <% end %>
50
50
  </div>
51
51
  <div class="col-6 col-lg-1 text-wrap">
52
52
  <% if batch.finished_at %>
53
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.batch.finished_at" %></div>
53
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.batch.finished_at" %></div>
54
54
  <%= relative_time(batch.finished_at) %>
55
55
  <% end %>
56
56
  </div>
57
57
  <div class="col-6 col-lg-1">
58
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.batch.jobs" %></div>
58
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.batch.jobs" %></div>
59
59
  <%= batch.jobs.count %>
60
60
  </div>
61
61
  <div class="col text-end">
@@ -64,7 +64,7 @@
64
64
  data: { bs_toggle: "collapse", bs_target: "##{dom_id(batch, 'properties')}" },
65
65
  aria: { expanded: false, controls: dom_id(batch, "state") } do %>
66
66
  <%= render_icon "info" %>
67
- <span class="visually-hidden"><%=t "good_job.actions.inspect" %></span>
67
+ <span class="visually-hidden"><%= t "good_job.actions.inspect" %></span>
68
68
  <% end %>
69
69
  </div>
70
70
  </div>
@@ -75,7 +75,7 @@
75
75
  <% end %>
76
76
  <% else %>
77
77
  <div class="list-group-item py-4 text-center text-muted">
78
- <%=t ".no_batches_found" %>
78
+ <%= t ".no_batches_found" %>
79
79
  </div>
80
80
  <% end %>
81
81
  </div>
@@ -1,4 +1,4 @@
1
- <h5><%=t ".title" %></h5>
1
+ <h5><%= t ".title" %></h5>
2
2
  <div class="card mb-4" data-live-poll-region="executions-table">
3
3
  <div class="list-group list-group-flush">
4
4
  <% executions.each do |execution| %>
@@ -10,12 +10,12 @@
10
10
  </div>
11
11
  <div class="col-md-2 small">
12
12
  <% if execution.queue_latency %>
13
- <%= format_duration execution.queue_latency %> <span class="text-muted"><%=t ".in_queue" %></span>
13
+ <%= format_duration execution.queue_latency %> <span class="text-muted"><%= t ".in_queue" %></span>
14
14
  <% end %>
15
15
  </div>
16
16
  <div class="col-md-2 small">
17
17
  <% if execution.runtime_latency %>
18
- <%= format_duration execution.runtime_latency %> <span class="text-muted"><%=t ".runtime" %></span>
18
+ <%= format_duration execution.runtime_latency %> <span class="text-muted"><%= t ".runtime" %></span>
19
19
  <% end %>
20
20
  </div>
21
21
  <div class="col">
@@ -28,20 +28,20 @@
28
28
  data: { bs_toggle: "collapse", bs_target: "##{dom_id(execution, 'params')}" },
29
29
  aria: { expanded: false, controls: dom_id(execution, "params") } do %>
30
30
  <%= render_icon "info" %>
31
- <span class="visually-hidden"><%=t "good_job.actions.inspect" %></span>
31
+ <span class="visually-hidden"><%= t "good_job.actions.inspect" %></span>
32
32
  <% end %>
33
33
  </div>
34
34
  </div>
35
35
  </div>
36
36
  <% if execution.error %>
37
37
  <div class="mt-3 small">
38
- <strong class="small text-danger"><%=t "good_job.shared.error" %>:</strong>
38
+ <strong class="small text-danger"><%= t "good_job.shared.error" %>:</strong>
39
39
  <code class="text-wrap text-break m-0 text-secondary-emphasis"><%= execution.error %></code>
40
40
  </div>
41
41
  <% if GoodJob::DiscreteExecution.backtrace_migrated? && execution.error_backtrace&.any? %>
42
- <%= tag.ul class: "nav nav-tabs small w-fit-content", id: dom_id(execution, :tab), role:"tablist" do %>
42
+ <%= tag.ul class: "nav nav-tabs small w-fit-content", id: dom_id(execution, :tab), role: "tablist" do %>
43
43
  <li class="nav-item" role="presentation">
44
- <%= tag.button t(".application_trace"), class: "nav-link active p-1", id: dom_id(execution, :application), data: { bs_toggle: "tab", bs_target: dom_id(execution, :"#application_pane") }, type: "button", role: "tab", aria: { controls: dom_id(execution, :application_pane), selected: true } %>
44
+ <%= tag.button t(".application_trace"), class: "nav-link active p-1", id: dom_id(execution, :application), data: { bs_toggle: "tab", bs_target: dom_id(execution, :"#application_pane") }, type: "button", role: "tab", aria: { controls: dom_id(execution, :application_pane), selected: true } %>
45
45
  </li>
46
46
  <li class="nav-item" role="presentation">
47
47
  <%= tag.button t(".full_trace"), class: "nav-link p-1", id: dom_id(execution, :full), data: { bs_toggle: "tab", bs_target: dom_id(execution, :"#full_pane") }, type: "button", role: "tab", aria: { controls: dom_id(execution, :full_pane), selected: false } %>
@@ -1,176 +1,178 @@
1
1
  <%= form_with(url: mass_update_jobs_path(filter.to_params), method: :put, local: true, data: { "checkbox-toggle": "job_ids" }) do |form| %>
2
- <div class="my-3 card" data-gj-poll-replace id="jobs-table">
3
- <div class="list-group list-group-flush text-nowrap table-jobs" role="table">
4
- <header class="list-group-item bg-body-tertiary">
5
- <div class="row small text-muted text-uppercase align-items-center">
6
- <div class="col-lg-4 d-flex gap-2 flex-wrap">
7
- <div class="form-check d-flex flex-row px-0 mb-0">
8
- <%= check_box_tag('toggle_job_ids', "1", false, data: { "checkbox-toggle-all": "job_ids" }) %>
9
- <%= label_tag('toggle_job_ids', t(".toggle_all_jobs"), class: "visually-hidden") %>
10
- </div>
11
- <%= form.button type: 'submit', name: 'mass_action', value: 'reschedule', class: 'ms-1 btn btn-sm btn-outline-secondary', title: t(".actions.reschedule_all"), data: { confirm: t(".actions.confirm_reschedule_all"), disable: true } do %>
12
- <span class="me-1"><%= render_icon "skip_forward" %></span> <%=t "good_job.actions.reschedule" %>
13
- <% end %>
14
-
15
- <%= form.button type: 'submit', name: 'mass_action', value: 'retry', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.retry_all"), data: { confirm: t(".actions.confirm_retry_all"), disable: true } do %>
16
- <span class="me-1"><%= render_icon "arrow_clockwise" %></span> <%=t "good_job.actions.retry" %>
17
- <% end %>
2
+ <div class="my-3 card" data-gj-poll-replace id="jobs-table">
3
+ <div class="list-group list-group-flush text-nowrap table-jobs" role="table">
4
+ <header class="list-group-item bg-body-tertiary">
5
+ <div class="row small text-muted text-uppercase align-items-center">
6
+ <div class="col-lg-4 d-flex gap-2 flex-wrap">
7
+ <div class="form-check d-flex flex-row px-0 mb-0">
8
+ <%= check_box_tag('toggle_job_ids', "1", false, data: { "checkbox-toggle-all": "job_ids" }) %>
9
+ <%= label_tag('toggle_job_ids', t(".toggle_all_jobs"), class: "visually-hidden") %>
10
+ </div>
11
+ <%= form.button type: 'submit', name: 'mass_action', value: 'reschedule', class: 'ms-1 btn btn-sm btn-outline-secondary', title: t(".actions.reschedule_all"), data: { confirm: t(".actions.confirm_reschedule_all"), disable: true } do %>
12
+ <span class="me-1"><%= render_icon "skip_forward" %></span> <%= t "good_job.actions.reschedule" %>
13
+ <% end %>
18
14
 
19
- <div class="btn-group" role="group">
20
- <%= form.button type: 'submit', name: 'mass_action', value: 'discard', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.discard_all"), data: { confirm: t(".actions.confirm_discard_all"), disable: true } do %>
21
- <span class="me-1"><%= render_icon "stop" %></span> <%=t "good_job.actions.discard" %>
15
+ <%= form.button type: 'submit', name: 'mass_action', value: 'retry', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.retry_all"), data: { confirm: t(".actions.confirm_retry_all"), disable: true } do %>
16
+ <span class="me-1"><%= render_icon "arrow_clockwise" %></span> <%= t "good_job.actions.retry" %>
22
17
  <% end %>
23
- <button id="destroy-dropdown-toggle" type="button" class="btn btn-sm btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
24
- <span class="visually-hidden"><%=t ".toggle_actions" %></span>
25
- </button>
26
- <ul class="dropdown-menu" aria-labelledby="destroy-dropdown-toggle">
27
- <li>
28
- <%= form.button type: 'submit', name: 'mass_action', value: 'destroy', class: 'btn dropdown-item', title: t(".actions.destroy_all"), data: { confirm: t(".actions.confirm_destroy_all"), disable: true } do %>
29
- <span class="me-1"><%= render_icon "trash" %></span> <%=t "good_job.actions.destroy" %>
30
- <% end %>
31
- </li>
32
- </ul>
33
- </div>
34
18
 
35
- </div>
36
- <div class="d-none d-lg-block col-lg-1 text-lg-center"><%=t "good_job.models.job.queue" %></div>
37
- <div class="d-none d-lg-block col-lg-1 text-lg-end"><%=t "good_job.models.job.priority" %></div>
38
- <div class="d-none d-lg-block col-lg-1 text-lg-end"><%=t "good_job.models.job.attempts" %></div>
39
- <div class="col text-end">
40
- <%= tag.button type: "button", class: "btn btn-sm text-muted", role: "button",
41
- data: { bs_toggle: "collapse", bs_target: ".job-params" },
42
- aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, "params")}" }.join(" ") } do %>
19
+ <div class="btn-group" role="group">
20
+ <%= form.button type: 'submit', name: 'mass_action', value: 'discard', class: 'btn btn-sm btn-outline-secondary', title: t(".actions.discard_all"), data: { confirm: t(".actions.confirm_discard_all"), disable: true } do %>
21
+ <span class="me-1"><%= render_icon "stop" %></span> <%= t "good_job.actions.discard" %>
22
+ <% end %>
23
+ <button id="destroy-dropdown-toggle" type="button" class="btn btn-sm btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-bs-toggle="dropdown" aria-expanded="false">
24
+ <span class="visually-hidden"><%= t ".toggle_actions" %></span>
25
+ </button>
26
+ <ul class="dropdown-menu" aria-labelledby="destroy-dropdown-toggle">
27
+ <li>
28
+ <%= form.button type: 'submit', name: 'mass_action', value: 'destroy', class: 'btn dropdown-item', title: t(".actions.destroy_all"), data: { confirm: t(".actions.confirm_destroy_all"), disable: true } do %>
29
+ <span class="me-1"><%= render_icon "trash" %></span> <%= t "good_job.actions.destroy" %>
30
+ <% end %>
31
+ </li>
32
+ </ul>
33
+ </div>
34
+
35
+ </div>
36
+ <div class="d-none d-lg-block col-lg-1 text-lg-center"><%= t "good_job.models.job.queue" %></div>
37
+ <div class="d-none d-lg-block col-lg-1 text-lg-end"><%= t "good_job.models.job.priority" %></div>
38
+ <div class="d-none d-lg-block col-lg-1 text-lg-end"><%= t "good_job.models.job.attempts" %></div>
39
+ <div class="col text-end">
40
+ <%= tag.button type: "button", class: "btn btn-sm text-muted", role: "button",
41
+ data: { bs_toggle: "collapse", bs_target: ".job-params" },
42
+ aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, 'params')}" }.join(" ") } do %>
43
43
  <%= render_icon "info" %>
44
- <span class="visually-hidden"><%=t "good_job.actions.inspect" %></span>
45
- <% end %>
46
- </div>
47
- </div>
48
- </header>
49
- <label role="row" class="list-group-item list-group-item-warning list-group-item-action py-2 d-none" data-checkbox-toggle-show="job_ids">
50
- <div class="row">
51
- <div class="col-auto">
52
- <%= check_box_tag "all_job_ids", 1, false, disabled: true, data: { "checkbox-toggle-show": "job_ids"} %>
44
+ <span class="visually-hidden"><%= t "good_job.actions.inspect" %></span>
45
+ <% end %>
46
+ </div>
53
47
  </div>
54
- <div class="col-auto">
55
- <%=t ".actions.apply_to_all", count: filter.filtered_count %>
48
+ </header>
49
+ <label role="row" class="list-group-item list-group-item-warning list-group-item-action py-2 d-none" data-checkbox-toggle-show="job_ids">
50
+ <div class="row">
51
+ <div class="col-auto">
52
+ <%= check_box_tag "all_job_ids", 1, false, disabled: true, data: { "checkbox-toggle-show": "job_ids" } %>
53
+ </div>
54
+ <div class="col-auto">
55
+ <%= t ".actions.apply_to_all", count: filter.filtered_count %>
56
+ </div>
56
57
  </div>
57
- </div>
58
- </label>
58
+ </label>
59
59
 
60
- <% if jobs.present? %>
61
- <% jobs.each do |job| %>
62
- <%= label_tag dom_id(job, :checkbox), id: dom_id(job), role: "row", class: "list-group-item list-group-item-action py-3" do %>
63
- <div class="row align-items-center">
64
- <div class="col-lg-4 d-flex">
65
- <%= check_box_tag 'job_ids[]', job.id, false, id: dom_id(job, :checkbox), data: { "checkbox-toggle-each": "job_ids" } %>
66
- <div class="ms-2">
67
- <%= tag.code link_to(job.id, job_path(job), class: "small text-muted text-decoration-none") %>
68
- <%= tag.h5 tag.code(link_to(job.display_name, job_path(job), class: "text-reset text-decoration-none")), class: "text-reset mb-0" %>
69
- <% if job.error %>
70
- <div class="mt-1 small">
71
- <strong class="small text-danger"><%=t "good_job.shared.error" %>:</strong>
72
- <code class="text-wrap text-break m-0 text-secondary-emphasis"><%= job.error %></code>
73
- </div>
74
- <% end %>
60
+ <% if jobs.present? %>
61
+ <% jobs.each do |job| %>
62
+ <%= label_tag dom_id(job, :checkbox), id: dom_id(job), role: "row", class: "list-group-item list-group-item-action py-3" do %>
63
+ <div class="row align-items-center">
64
+ <div class="col-lg-4 d-flex">
65
+ <%= check_box_tag 'job_ids[]', job.id, false, id: dom_id(job, :checkbox), data: { "checkbox-toggle-each": "job_ids" } %>
66
+ <div class="ms-2">
67
+ <%= tag.code link_to(job.id, job_path(job), class: "small text-muted text-decoration-none") %>
68
+ <%= tag.h5 tag.code(link_to(job.display_name, job_path(job), class: "text-reset text-decoration-none")), class: "text-reset mb-0" %>
69
+ <% if job.error %>
70
+ <div class="mt-1 small">
71
+ <strong class="small text-danger"><%= t "good_job.shared.error" %>:</strong>
72
+ <code class="text-wrap text-break m-0 text-secondary-emphasis"><%= job.error %></code>
73
+ </div>
74
+ <% end %>
75
+ </div>
75
76
  </div>
76
- </div>
77
- <div class="col-4 col-lg-1 text-lg-center">
78
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.job.queue" %></div>
79
- <span class="badge bg-primary font-monospace"><%= job.queue_name %></span>
80
- </div>
81
- <div class="col-4 col-lg-1 text-lg-end">
82
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.job.priority" %></div>
83
- <%= job.priority %>
84
- </div>
85
- <div class="col-4 col-lg-1 text-lg-end">
86
- <div class="d-lg-none small text-muted mt-1"><%=t "good_job.models.job.attempts" %></div>
87
- <% if job.executions_count > 0 && job.status != :succeeded %>
88
- <%= tag.span job.executions_count, class: "badge rounded-pill bg-danger", data: {
77
+ <div class="col-4 col-lg-1 text-lg-center">
78
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.job.queue" %></div>
79
+ <span class="badge bg-primary font-monospace"><%= job.queue_name %></span>
80
+ </div>
81
+ <div class="col-4 col-lg-1 text-lg-end">
82
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.job.priority" %></div>
83
+ <%= job.priority %>
84
+ </div>
85
+ <div class="col-4 col-lg-1 text-lg-end">
86
+ <div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.job.attempts" %></div>
87
+ <% if job.executions_count > 0 && job.status != :succeeded %>
88
+ <%= tag.span job.executions_count, class: "badge rounded-pill bg-danger",
89
+ data: {
89
90
  bs_toggle: "popover",
90
91
  bs_trigger: "hover focus click",
91
92
  bs_placement: "bottom",
92
93
  bs_content: job.display_error,
93
- } %>
94
- <% else %>
95
- <span class="badge bg-secondary rounded-pill"><%= job.executions_count %></span>
96
- <% end %>
97
- </div>
98
- <div class="mt-3 mt-lg-0 col">
99
- <div class="d-flex gap-3 align-items-start justify-content-end">
100
- <%= tag.span relative_time(job.last_status_at), class: "small mt-1" %>
101
- <div>
102
- <%= status_badge job.status %>
103
- <% if job.status == :discarded && job.class.error_event_migrated? && job.error_event %>
104
- <div class="text-black text-center" >
105
- <small><%= t(job.error_event, scope: 'good_job.error_event') %></small>
106
- </div>
107
- <% end %>
108
- </div>
94
+ }
95
+ %>
96
+ <% else %>
97
+ <span class="badge bg-secondary rounded-pill"><%= job.executions_count %></span>
98
+ <% end %>
99
+ </div>
100
+ <div class="mt-3 mt-lg-0 col">
101
+ <div class="d-flex gap-3 align-items-start justify-content-end">
102
+ <%= tag.span relative_time(job.last_status_at), class: "small mt-1" %>
103
+ <div>
104
+ <%= status_badge job.status %>
105
+ <% if job.status == :discarded && job.class.error_event_migrated? && job.error_event %>
106
+ <div class="text-black text-center">
107
+ <small><%= t(job.error_event, scope: 'good_job.error_event') %></small>
108
+ </div>
109
+ <% end %>
110
+ </div>
109
111
 
110
- <div class="dropdown float-end">
111
- <button class="d-flex align-items-center btn btn-sm" type="button" id="<%= dom_id(job, :actions) %>" data-bs-toggle="dropdown" aria-expanded="false">
112
- <%= render_icon "dots" %>
113
- <span class="visually-hidden"><%=t ".actions.title" %></span>
114
- </button>
115
- <ul class="dropdown-menu shadow" aria-labelledby="<%= dom_id(job, :actions) %>">
116
- <li>
117
- <% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %>
118
- <%= link_to reschedule_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_reschedulable}", title: t("good_job.jobs.actions.reschedule"), data: { confirm: t("good_job.jobs.actions.confirm_reschedule"), disable: true } do %>
119
- <%= render_icon "skip_forward" %>
120
- <%=t "good_job.actions.reschedule" %>
121
- <% end %>
122
- </li>
123
- <li>
124
- <% job_discardable = job.status.in? [:scheduled, :retried, :queued] %>
125
- <%= link_to discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: t("good_job.jobs.actions.discard"), data: { confirm: t("good_job.jobs.actions.confirm_discard"), disable: true } do %>
126
- <%= render_icon "stop" %>
127
- <%=t "good_job.actions.discard" %>
128
- <% end %>
129
- </li>
130
- <li>
131
- <% job_force_discardable = job.status.in? [:running] %>
132
- <%= link_to force_discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_force_discardable}", title: t("good_job.jobs.actions.force_discard"), data: { confirm: t("good_job.jobs.actions.confirm_force_discard"), disable: true } do %>
133
- <%= render_icon "eject" %>
134
- <%=t "good_job.actions.force_discard" %>
135
- <% end %>
136
- </li>
137
- <li>
138
- <%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t("good_job.jobs.actions.retry"), data: { confirm: t("good_job.jobs.actions.confirm_retry"), disable: true } do %>
139
- <%= render_icon "arrow_clockwise" %>
140
- <%=t "good_job.actions.retry" %>
141
- <% end %>
142
- </li>
143
- <li>
144
- <%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :succeeded]}", title: t("good_job.jobs.actions.destroy"), data: { confirm: t("good_job.jobs.actions.confirm_destroy"), disable: true } do %>
145
- <%= render_icon "trash" %>
146
- <%=t "good_job.actions.destroy" %>
147
- <% end %>
148
- </li>
112
+ <div class="dropdown float-end">
113
+ <button class="d-flex align-items-center btn btn-sm" type="button" id="<%= dom_id(job, :actions) %>" data-bs-toggle="dropdown" aria-expanded="false">
114
+ <%= render_icon "dots" %>
115
+ <span class="visually-hidden"><%= t ".actions.title" %></span>
116
+ </button>
117
+ <ul class="dropdown-menu shadow" aria-labelledby="<%= dom_id(job, :actions) %>">
118
+ <li>
119
+ <% job_reschedulable = job.status.in? [:scheduled, :retried, :queued] %>
120
+ <%= link_to reschedule_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_reschedulable}", title: t("good_job.jobs.actions.reschedule"), data: { confirm: t("good_job.jobs.actions.confirm_reschedule"), disable: true } do %>
121
+ <%= render_icon "skip_forward" %>
122
+ <%= t "good_job.actions.reschedule" %>
123
+ <% end %>
124
+ </li>
125
+ <li>
126
+ <% job_discardable = job.status.in? [:scheduled, :retried, :queued] %>
127
+ <%= link_to discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_discardable}", title: t("good_job.jobs.actions.discard"), data: { confirm: t("good_job.jobs.actions.confirm_discard"), disable: true } do %>
128
+ <%= render_icon "stop" %>
129
+ <%= t "good_job.actions.discard" %>
130
+ <% end %>
131
+ </li>
132
+ <li>
133
+ <% job_force_discardable = job.status.in? [:running] %>
134
+ <%= link_to force_discard_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job_force_discardable}", title: t("good_job.jobs.actions.force_discard"), data: { confirm: t("good_job.jobs.actions.confirm_force_discard"), disable: true } do %>
135
+ <%= render_icon "eject" %>
136
+ <%= t "good_job.actions.force_discard" %>
137
+ <% end %>
138
+ </li>
139
+ <li>
140
+ <%= link_to retry_job_path(job.id), method: :put, class: "dropdown-item #{'disabled' unless job.status == :discarded}", title: t("good_job.jobs.actions.retry"), data: { confirm: t("good_job.jobs.actions.confirm_retry"), disable: true } do %>
141
+ <%= render_icon "arrow_clockwise" %>
142
+ <%= t "good_job.actions.retry" %>
143
+ <% end %>
144
+ </li>
145
+ <li>
146
+ <%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :succeeded]}", title: t("good_job.jobs.actions.destroy"), data: { confirm: t("good_job.jobs.actions.confirm_destroy"), disable: true } do %>
147
+ <%= render_icon "trash" %>
148
+ <%= t "good_job.actions.destroy" %>
149
+ <% end %>
150
+ </li>
149
151
 
150
- <li>
151
- <%= link_to "##{dom_id(job, 'params')}",
152
- class: "dropdown-item",
153
- data: { bs_toggle: "collapse" },
154
- aria: { expanded: false, controls: dom_id(job, "params") } do %>
155
- <%= render_icon "info" %>
156
- <%=t "good_job.actions.inspect" %>
157
- <% end %>
158
- </li>
159
- </ul>
152
+ <li>
153
+ <%= link_to "##{dom_id(job, 'params')}",
154
+ class: "dropdown-item",
155
+ data: { bs_toggle: "collapse" },
156
+ aria: { expanded: false, controls: dom_id(job, "params") } do %>
157
+ <%= render_icon "info" %>
158
+ <%= t "good_job.actions.inspect" %>
159
+ <% end %>
160
+ </li>
161
+ </ul>
162
+ </div>
160
163
  </div>
161
164
  </div>
162
165
  </div>
163
- </div>
164
- <% end %>
165
- <%= tag.div id: dom_id(job, "params"), class: "job-params list-group-item collapse small bg-dark text-light" do %>
166
- <%= tag.pre JSON.pretty_generate(job.display_serialized_params) %>
166
+ <% end %>
167
+ <%= tag.div id: dom_id(job, "params"), class: "job-params list-group-item collapse small bg-dark text-light" do %>
168
+ <%= tag.pre JSON.pretty_generate(job.display_serialized_params) %>
169
+ <% end %>
167
170
  <% end %>
171
+ <% else %>
172
+ <div class="list-group-item py-4 text-center text-muted">
173
+ <%= t ".no_jobs_found" %>
174
+ </div>
168
175
  <% end %>
169
- <% else %>
170
- <div class="list-group-item py-4 text-center text-muted">
171
- <%=t ".no_jobs_found" %>
172
- </div>
173
- <% end %>
176
+ </div>
174
177
  </div>
175
- </div>
176
178
  <% end %>
@@ -12,7 +12,7 @@
12
12
  <div class="me-md-2 mb-2 mb-md-0">
13
13
  <%= label_tag "job_queue_filter", t(".queue_name"), class: "visually-hidden" %>
14
14
  <select name="queue_name" id="job_queue_filter" class="form-select form-select-sm">
15
- <option value="" <%= "selected='selected'" if params[:queue_name].blank? %>><%=t ".all_queues" %></option>
15
+ <option value="" <%= "selected='selected'" if params[:queue_name].blank? %>><%= t ".all_queues" %></option>
16
16
 
17
17
  <% filter.queues.each do |name, count| %>
18
18
  <option value="<%= name.to_param %>" <%= "selected='selected'" if params[:queue_name] == name %>><%= name %> (<%= number_with_delimiter(count, translate_hash('good_job.number.format')) %>)</option>
@@ -23,7 +23,7 @@
23
23
  <div class="me-md-2 mb-2 mb-md-0">
24
24
  <%= label_tag "job_class_filter", t(".job_name"), class: "visually-hidden" %>
25
25
  <select name="job_class" id="job_class_filter" class="form-select form-select-sm">
26
- <option value="" <%= "selected='selected'" if params[:job_class].blank? %>><%=t ".all_jobs" %></option>
26
+ <option value="" <%= "selected='selected'" if params[:job_class].blank? %>><%= t ".all_jobs" %></option>
27
27
 
28
28
  <% filter.job_classes.each do |name, count| %>
29
29
  <option value="<%= name.to_param %>" <%= "selected='selected'" if params[:job_class] == name %>><%= name %> (<%= number_with_delimiter(count, translate_hash('good_job.number.format')) %>)</option>
@@ -33,14 +33,14 @@
33
33
 
34
34
  <div class="me-md-2 mb-2 mb-md-0 flex-fill">
35
35
  <%= label_tag "query", t(".search"), class: "visually-hidden" %>
36
- <%= search_field_tag "query", params[:query], class: "form-control form-control-sm", placeholder: t(".placeholder") %>
36
+ <%= search_field_tag "query", params[:query], class: "form-control form-control-sm", placeholder: t(".placeholder"), autocomplete: "off" %>
37
37
  </div>
38
38
 
39
39
  <div class="d-flex flex-col align-items-end">
40
40
  <div>
41
41
  <%= form.submit t(".search"), name: nil, class: "btn btn-primary btn-sm" %>
42
42
  <%= link_to filter.to_params(job_class: nil, state: nil, queue_name: nil, query: nil), class: "btn btn-secondary btn-sm" do %>
43
- <%=t ".clear" %>
43
+ <%= t ".clear" %>
44
44
  <% end %>
45
45
  </div>
46
46
  </div>
@@ -49,21 +49,21 @@
49
49
 
50
50
  <ul data-controller="async-values" data-async-values-url-value="<%= metrics_job_status_path %>" data-live-poll-region="filter-tabs" class="nav nav-tabs my-3">
51
51
  <li class="nav-item">
52
- <%= link_to t(".all"), filter.to_params(state: nil), class: "nav-link #{"active" unless params[:state].present?}" %>
52
+ <%= link_to t(".all"), filter.to_params(state: nil), class: "nav-link #{'active' if params[:state].blank?}" %>
53
53
  </li>
54
54
 
55
55
  <% filter.state_names.each do |name| %>
56
56
  <li class="nav-item">
57
- <%= link_to filter.to_params(state: name), class: "nav-link #{"active" if params[:state] == name}" do %>
57
+ <%= link_to filter.to_params(state: name), class: "nav-link #{'active' if params[:state] == name}" do %>
58
58
  <%= t(name, scope: 'good_job.status') %>
59
- <span data-async-values-target="value", data-async-values-key="<%= name %>" data-async-values-zero-class="bg-secondary" class="badge bg-primary rounded-pill d-none"></span>
59
+ <span data-async-values-target="value" data-async-values-key="<%= name %>" data-async-values-zero-class="bg-secondary" class="badge bg-primary rounded-pill d-none"></span>
60
60
  <% end %>
61
61
  </li>
62
62
  <% end %>
63
63
  </ul>
64
64
  </div>
65
65
 
66
- <%= javascript_tag nonce: true do %>
66
+ <script nonce="<%= content_security_policy_nonce %>">
67
67
  document.addEventListener("DOMContentLoaded", () => {
68
68
  document.querySelectorAll("#job_class_filter, #job_queue_filter").forEach((filter) => {
69
69
  filter.addEventListener("change", () => {
@@ -71,5 +71,5 @@
71
71
  });
72
72
  })
73
73
  })
74
- <% end %>
74
+ </script>
75
75
  </div>
@@ -23,7 +23,7 @@
23
23
  </li>
24
24
  <li class="nav-item">
25
25
  <%= link_to batches_path, class: ["nav-link", ("active" if controller_name == 'batches')] do %>
26
- <%=t ".batches" %>
26
+ <%= t ".batches" %>
27
27
  <span data-async-values-target="value" data-async-values-key="batches_count" class="badge bg-secondary rounded-pill d-none"></span>
28
28
  <% end %>
29
29
  </li>
@@ -5,7 +5,7 @@
5
5
  </div>
6
6
  <div class="flex-fill text-end">
7
7
  <% last_updated_at = Time.current.utc.iso8601 %>
8
- <%= t(".last_updated") %>&nbsp;<time id="page-updated-at" datetime="<%= last_updated_at %>"><%== last_updated_at %></time>
8
+ <%= t(".last_updated") %>&nbsp;<time id="page-updated-at" datetime="<%= last_updated_at %>"><%= last_updated_at %></time>
9
9
  </div>
10
10
  </div>
11
11
  </nav>
@@ -12,13 +12,13 @@
12
12
  to reduce potential screen flickering during reloading of your site."
13
13
  https://getbootstrap.com/docs/5.3/customize/color-modes/#javascript
14
14
  %>
15
- <%= tag.script "", nonce: content_security_policy_nonce do %>
15
+ <script nonce="<%= content_security_policy_nonce %>">
16
16
  let theme = localStorage.getItem('good_job-theme');
17
17
  if (!["light", "dark"].includes(theme)) {
18
18
  theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
19
19
  }
20
20
  document.documentElement.setAttribute('data-bs-theme', theme);
21
- <% end %>
21
+ </script>
22
22
 
23
23
  <%# Do not use asset tag helpers to avoid paths being overriden by config.asset_host %>
24
24
  <%= tag.link rel: "stylesheet", href: frontend_static_path(:bootstrap, format: :css, v: GoodJob::VERSION, locale: nil), nonce: content_security_policy_nonce %>
@@ -6,7 +6,7 @@ module GoodJob
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  def batch
9
- @_batch ||= CurrentThread.execution&.batch&.to_batch
9
+ @_batch ||= CurrentThread.execution&.batch&.to_batch if CurrentThread.execution.present? && CurrentThread.execution.active_job_id == job_id
10
10
  end
11
11
  alias batch? batch
12
12
  end
@@ -75,7 +75,7 @@ module GoodJob
75
75
  key = job.good_job_concurrency_key
76
76
  next if key.blank?
77
77
 
78
- if CurrentThread.execution.blank?
78
+ if CurrentThread.execution.blank? || CurrentThread.execution.active_job_id != job_id
79
79
  logger.debug("Ignoring concurrency limits because the job is executed with `perform_now`.")
80
80
  next
81
81
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GoodJob
4
4
  # GoodJob gem version.
5
- VERSION = '3.28.0'
5
+ VERSION = '3.28.1'
6
6
 
7
7
  # GoodJob version as Gem::Version object
8
8
  GEM_VERSION = Gem::Version.new(VERSION)
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.28.0
4
+ version: 3.28.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-19 00:00:00.000000000 Z
11
+ date: 2024-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -431,7 +431,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
431
431
  - !ruby/object:Gem::Version
432
432
  version: '0'
433
433
  requirements: []
434
- rubygems_version: 3.5.4
434
+ rubygems_version: 3.5.9
435
435
  signing_key:
436
436
  specification_version: 4
437
437
  summary: A multithreaded, Postgres-based ActiveJob backend for Ruby on Rails