good_job 3.18.1 → 3.18.3
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 +33 -0
- data/app/filters/good_job/batches_filter.rb +1 -1
- data/app/models/good_job/batch.rb +4 -0
- data/app/models/good_job/cron_entry.rb +28 -28
- data/app/views/good_job/cron_entries/index.html.erb +2 -2
- data/lib/good_job/callable.rb +12 -0
- data/lib/good_job/notifier.rb +28 -14
- data/lib/good_job/probe_server.rb +1 -1
- data/lib/good_job/version.rb +1 -1
- data/lib/good_job.rb +1 -0
- metadata +3 -58
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 930bb77e947ac155ee655210ab15ef32ac40fc2d6487eaf80b0005d7e5675156
|
|
4
|
+
data.tar.gz: b3e26f0b7f4d60483a6d0646d5797654e447542b8d6cb9eca22e2cb7cbfaac78
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d92deaa0fa930cd8e8bf9b6b51f37c6d8ec1b75d221d939b6b5d2cb2ec30153931873951bbfca9af5dd24867e6131133f865368845a2cf783e8212137ed3bd76
|
|
7
|
+
data.tar.gz: 0c3ff2fd89cb38061ab145d74180596334fc8f38cba5f2a61d11fcf791d03534b823361bd9546cea4cea316d04d3cfba979d459b1b3d8185386298cdb71593a0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v3.18.3](https://github.com/bensheldon/good_job/tree/v3.18.3) (2023-09-16)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.18.2...v3.18.3)
|
|
6
|
+
|
|
7
|
+
**Fixed bugs:**
|
|
8
|
+
|
|
9
|
+
- Allow Probe Server's `/connect` to handle a certain number of reconnects before statusing [\#1075](https://github.com/bensheldon/good_job/pull/1075) ([bensheldon](https://github.com/bensheldon))
|
|
10
|
+
|
|
11
|
+
**Closed issues:**
|
|
12
|
+
|
|
13
|
+
- ActiveRecord::RecordNotUnique good\_jobs.id error in rspec test suite [\#1072](https://github.com/bensheldon/good_job/issues/1072)
|
|
14
|
+
- Probe failures on heavy usage of dashboard\(?\) [\#1068](https://github.com/bensheldon/good_job/issues/1068)
|
|
15
|
+
|
|
16
|
+
**Merged pull requests:**
|
|
17
|
+
|
|
18
|
+
- Bump actions/checkout from 3 to 4 [\#1070](https://github.com/bensheldon/good_job/pull/1070) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
19
|
+
- Add Skylight for demo site; create distinct development, lint, demo, production Gemfile groups; a little bit of Rubocop [\#1069](https://github.com/bensheldon/good_job/pull/1069) ([bensheldon](https://github.com/bensheldon))
|
|
20
|
+
- Add JRuby 9.4 to testing matrix; nerf ActiveJob::TestQueueAdapter overrides [\#1067](https://github.com/bensheldon/good_job/pull/1067) ([bensheldon](https://github.com/bensheldon))
|
|
21
|
+
- Reorganize dependencies to make booting JRuby easier [\#1066](https://github.com/bensheldon/good_job/pull/1066) ([bensheldon](https://github.com/bensheldon))
|
|
22
|
+
- Slight refactoring to CronEntry [\#1063](https://github.com/bensheldon/good_job/pull/1063) ([bensheldon](https://github.com/bensheldon))
|
|
23
|
+
|
|
24
|
+
## [v3.18.2](https://github.com/bensheldon/good_job/tree/v3.18.2) (2023-09-02)
|
|
25
|
+
|
|
26
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.18.1...v3.18.2)
|
|
27
|
+
|
|
28
|
+
**Fixed bugs:**
|
|
29
|
+
|
|
30
|
+
- Fix compatibility with Global ID v1.2.0 [\#1064](https://github.com/bensheldon/good_job/pull/1064) ([bensheldon](https://github.com/bensheldon))
|
|
31
|
+
|
|
32
|
+
**Merged pull requests:**
|
|
33
|
+
|
|
34
|
+
- Bump pg from 1.5.3 to 1.5.4 [\#1061](https://github.com/bensheldon/good_job/pull/1061) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
35
|
+
|
|
3
36
|
## [v3.18.1](https://github.com/bensheldon/good_job/tree/v3.18.1) (2023-08-30)
|
|
4
37
|
|
|
5
38
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.18.0...v3.18.1)
|
|
@@ -60,29 +60,15 @@ module GoodJob # :nodoc:
|
|
|
60
60
|
|
|
61
61
|
def next_at(previously_at: nil)
|
|
62
62
|
if cron_proc?
|
|
63
|
-
result = Rails.application.executor.wrap { cron.call(previously_at ||
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
result = Rails.application.executor.wrap { cron.call(previously_at || last_job_at) }
|
|
64
|
+
if result.is_a?(String)
|
|
65
|
+
Fugit.parse(result).next_time.to_t
|
|
66
|
+
else
|
|
67
|
+
result
|
|
68
|
+
end
|
|
69
|
+
else
|
|
70
|
+
fugit.next_time.to_t
|
|
68
71
|
end
|
|
69
|
-
fugit.next_time.to_t
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def schedule
|
|
73
|
-
return "Custom schedule" if cron_proc?
|
|
74
|
-
|
|
75
|
-
fugit.original
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def jobs
|
|
79
|
-
GoodJob::Job.where(cron_key: key)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def last_at
|
|
83
|
-
return if last_job.blank?
|
|
84
|
-
|
|
85
|
-
(last_job.cron_at || last_job.created_at).localtime
|
|
86
72
|
end
|
|
87
73
|
|
|
88
74
|
def enabled?
|
|
@@ -113,15 +99,11 @@ module GoodJob # :nodoc:
|
|
|
113
99
|
false
|
|
114
100
|
end
|
|
115
101
|
|
|
116
|
-
def last_job
|
|
117
|
-
jobs.order("cron_at DESC NULLS LAST").first
|
|
118
|
-
end
|
|
119
|
-
|
|
120
102
|
def display_properties
|
|
121
103
|
{
|
|
122
104
|
key: key,
|
|
123
105
|
class: job_class,
|
|
124
|
-
cron:
|
|
106
|
+
cron: display_schedule,
|
|
125
107
|
set: display_property(set),
|
|
126
108
|
description: display_property(description),
|
|
127
109
|
}.tap do |properties|
|
|
@@ -130,6 +112,24 @@ module GoodJob # :nodoc:
|
|
|
130
112
|
end
|
|
131
113
|
end
|
|
132
114
|
|
|
115
|
+
def display_schedule
|
|
116
|
+
cron_proc? ? display_property(cron) : fugit.original
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def jobs
|
|
120
|
+
GoodJob::Job.where(cron_key: key)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def last_job
|
|
124
|
+
jobs.order("cron_at DESC NULLS LAST").first
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def last_job_at
|
|
128
|
+
return if last_job.blank?
|
|
129
|
+
|
|
130
|
+
(last_job.cron_at || last_job.created_at).localtime
|
|
131
|
+
end
|
|
132
|
+
|
|
133
133
|
private
|
|
134
134
|
|
|
135
135
|
def cron
|
|
@@ -163,7 +163,7 @@ module GoodJob # :nodoc:
|
|
|
163
163
|
case value
|
|
164
164
|
when NilClass
|
|
165
165
|
"None"
|
|
166
|
-
when
|
|
166
|
+
when Callable
|
|
167
167
|
"Lambda/Callable"
|
|
168
168
|
else
|
|
169
169
|
value
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
<div class="col-12 col-lg-2 text-wrap"><%= tag.span tag.code(cron_entry.job_class), class: "fs-5 mb-0" %></div>
|
|
32
32
|
<div class="col-6 col-lg-2 text-wrap">
|
|
33
33
|
<div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.cron.schedule" %></div>
|
|
34
|
-
<span class="font-monospace fw-bold"><%= cron_entry.
|
|
34
|
+
<span class="font-monospace fw-bold"><%= cron_entry.display_schedule %></span>
|
|
35
35
|
</div>
|
|
36
36
|
<div class="col-6 col-lg-2 text-wrap small">
|
|
37
37
|
<div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.cron.next_scheduled" %></div>
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
<div class="col-6 col-lg-2 text-wrap small">
|
|
41
41
|
<% if cron_entry.last_job.present? %>
|
|
42
42
|
<div class="d-lg-none small text-muted mt-1"><%= t "good_job.models.cron.last_run" %></div>
|
|
43
|
-
<%= link_to relative_time(cron_entry.
|
|
43
|
+
<%= link_to relative_time(cron_entry.last_job_at), cron_entry_path(cron_entry), title: "Job #{cron_entry.last_job.id}" %>
|
|
44
44
|
<% end %>
|
|
45
45
|
</div>
|
|
46
46
|
<div class="col d-flex gap-3 justify-content-end">
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GoodJob
|
|
4
|
+
# An object that has case-equality to a Proc or Lambda by responding to #call.
|
|
5
|
+
# This can be used to duck-type match in a case statement.
|
|
6
|
+
module Callable
|
|
7
|
+
# Whether the object responds to #call
|
|
8
|
+
def self.===(other)
|
|
9
|
+
other.respond_to?(:call)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
data/lib/good_job/notifier.rb
CHANGED
|
@@ -24,6 +24,9 @@ module GoodJob # :nodoc:
|
|
|
24
24
|
WAIT_INTERVAL = 1
|
|
25
25
|
# Seconds to wait if database cannot be connected to
|
|
26
26
|
RECONNECT_INTERVAL = 5
|
|
27
|
+
# Number of consecutive connection errors before reporting an error
|
|
28
|
+
CONNECTION_ERRORS_REPORTING_THRESHOLD = 6
|
|
29
|
+
|
|
27
30
|
# Connection errors that will wait {RECONNECT_INTERVAL} before reconnecting
|
|
28
31
|
CONNECTION_ERRORS = %w[
|
|
29
32
|
ActiveRecord::ConnectionNotEstablished
|
|
@@ -31,7 +34,6 @@ module GoodJob # :nodoc:
|
|
|
31
34
|
PG::UnableToSend
|
|
32
35
|
PG::Error
|
|
33
36
|
].freeze
|
|
34
|
-
CONNECTION_ERRORS_REPORTING_THRESHOLD = 3
|
|
35
37
|
|
|
36
38
|
# @!attribute [r] instances
|
|
37
39
|
# @!scope class
|
|
@@ -69,8 +71,8 @@ module GoodJob # :nodoc:
|
|
|
69
71
|
@mutex = Mutex.new
|
|
70
72
|
@shutdown_event = Concurrent::Event.new.tap(&:set)
|
|
71
73
|
@running = Concurrent::AtomicBoolean.new(false)
|
|
72
|
-
@connected = Concurrent::
|
|
73
|
-
@listening = Concurrent::
|
|
74
|
+
@connected = Concurrent::Event.new
|
|
75
|
+
@listening = Concurrent::Event.new
|
|
74
76
|
@connection_errors_count = Concurrent::AtomicFixnum.new(0)
|
|
75
77
|
@connection_errors_reported = Concurrent::AtomicBoolean.new(false)
|
|
76
78
|
@enable_listening = enable_listening
|
|
@@ -85,15 +87,25 @@ module GoodJob # :nodoc:
|
|
|
85
87
|
end
|
|
86
88
|
|
|
87
89
|
# Tests whether the notifier is active and has acquired a dedicated database connection.
|
|
90
|
+
# @param timeout [Numeric, nil] Seconds to wait for condition to be true, -1 is forever
|
|
88
91
|
# @return [true, false, nil]
|
|
89
|
-
def connected?
|
|
90
|
-
|
|
92
|
+
def connected?(timeout: nil)
|
|
93
|
+
if timeout.nil?
|
|
94
|
+
@connected.set?
|
|
95
|
+
else
|
|
96
|
+
@connected.wait(timeout == -1 ? nil : timeout)
|
|
97
|
+
end
|
|
91
98
|
end
|
|
92
99
|
|
|
93
100
|
# Tests whether the notifier is listening for new messages.
|
|
101
|
+
# @param timeout [Numeric, nil] Seconds to wait for condition to be true, -1 is forever
|
|
94
102
|
# @return [true, false, nil]
|
|
95
|
-
def listening?
|
|
96
|
-
|
|
103
|
+
def listening?(timeout: nil)
|
|
104
|
+
if timeout.nil?
|
|
105
|
+
@listening.set?
|
|
106
|
+
else
|
|
107
|
+
@listening.wait(timeout == -1 ? nil : timeout)
|
|
108
|
+
end
|
|
97
109
|
end
|
|
98
110
|
|
|
99
111
|
def shutdown?
|
|
@@ -114,11 +126,12 @@ module GoodJob # :nodoc:
|
|
|
114
126
|
|
|
115
127
|
if @executor.shutdown? || @task&.complete?
|
|
116
128
|
# clean up in the even the executor is killed
|
|
117
|
-
@connected.
|
|
118
|
-
@listening.
|
|
129
|
+
@connected.reset
|
|
130
|
+
@listening.reset
|
|
119
131
|
@shutdown_event.set
|
|
120
132
|
else
|
|
121
133
|
@shutdown_event.wait(timeout == -1 ? nil : timeout) unless timeout.nil?
|
|
134
|
+
@connected.reset if @shutdown_event.set?
|
|
122
135
|
end
|
|
123
136
|
@shutdown_event.set?
|
|
124
137
|
end
|
|
@@ -152,6 +165,7 @@ module GoodJob # :nodoc:
|
|
|
152
165
|
if connection_error
|
|
153
166
|
@connection_errors_count.increment
|
|
154
167
|
if @connection_errors_reported.false? && @connection_errors_count.value >= CONNECTION_ERRORS_REPORTING_THRESHOLD
|
|
168
|
+
@connected.reset
|
|
155
169
|
GoodJob._on_thread_error(thread_error)
|
|
156
170
|
@connection_errors_reported.make_true
|
|
157
171
|
end
|
|
@@ -180,15 +194,17 @@ module GoodJob # :nodoc:
|
|
|
180
194
|
end
|
|
181
195
|
|
|
182
196
|
def create_listen_task(delay: 0)
|
|
183
|
-
@task = Concurrent::ScheduledTask.new(delay, args: [@recipients, @running, @executor, @enable_listening, @listening], executor: @executor) do |thr_recipients, thr_running, thr_executor, thr_enable_listening, thr_listening|
|
|
197
|
+
@task = Concurrent::ScheduledTask.new(delay, args: [@recipients, @running, @executor, @enable_listening, @connected, @listening], executor: @executor) do |thr_recipients, thr_running, thr_executor, thr_enable_listening, thr_connected, thr_listening|
|
|
184
198
|
with_connection do
|
|
199
|
+
thr_connected.set
|
|
200
|
+
|
|
185
201
|
begin
|
|
186
202
|
Rails.application.executor.wrap do
|
|
187
203
|
run_callbacks :listen do
|
|
188
204
|
if thr_enable_listening
|
|
189
205
|
ActiveSupport::Notifications.instrument("notifier_listen.good_job") do
|
|
190
206
|
connection.execute("LISTEN #{CHANNEL}")
|
|
191
|
-
thr_listening.
|
|
207
|
+
thr_listening.set
|
|
192
208
|
end
|
|
193
209
|
end
|
|
194
210
|
end
|
|
@@ -216,7 +232,7 @@ module GoodJob # :nodoc:
|
|
|
216
232
|
run_callbacks :unlisten do
|
|
217
233
|
if thr_enable_listening
|
|
218
234
|
ActiveSupport::Notifications.instrument("notifier_unlisten.good_job") do
|
|
219
|
-
thr_listening.
|
|
235
|
+
thr_listening.reset
|
|
220
236
|
connection.execute("UNLISTEN *")
|
|
221
237
|
end
|
|
222
238
|
end
|
|
@@ -237,11 +253,9 @@ module GoodJob # :nodoc:
|
|
|
237
253
|
end
|
|
238
254
|
end
|
|
239
255
|
connection.execute("SET application_name = #{connection.quote(self.class.name)}")
|
|
240
|
-
@connected.make_true
|
|
241
256
|
|
|
242
257
|
yield
|
|
243
258
|
ensure
|
|
244
|
-
@connected.make_false
|
|
245
259
|
connection&.disconnect!
|
|
246
260
|
self.connection = nil
|
|
247
261
|
end
|
|
@@ -37,7 +37,7 @@ module GoodJob
|
|
|
37
37
|
started ? [200, {}, ["Started"]] : [503, {}, ["Not started"]]
|
|
38
38
|
when '/status/connected'
|
|
39
39
|
connected = GoodJob::Scheduler.instances.any? && GoodJob::Scheduler.instances.all?(&:running?) &&
|
|
40
|
-
GoodJob::Notifier.instances.any? && GoodJob::Notifier.instances.all?(&:
|
|
40
|
+
GoodJob::Notifier.instances.any? && GoodJob::Notifier.instances.all?(&:connected?)
|
|
41
41
|
connected ? [200, {}, ["Connected"]] : [503, {}, ["Not connected"]]
|
|
42
42
|
else
|
|
43
43
|
[404, {}, ["Not found"]]
|
data/lib/good_job/version.rb
CHANGED
data/lib/good_job.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.18.
|
|
4
|
+
version: 3.18.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ben Sheldon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-09-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activejob
|
|
@@ -122,62 +122,6 @@ dependencies:
|
|
|
122
122
|
- - ">="
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '0'
|
|
125
|
-
- !ruby/object:Gem::Dependency
|
|
126
|
-
name: dotenv
|
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
|
128
|
-
requirements:
|
|
129
|
-
- - "~>"
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: 2.7.6
|
|
132
|
-
type: :development
|
|
133
|
-
prerelease: false
|
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
-
requirements:
|
|
136
|
-
- - "~>"
|
|
137
|
-
- !ruby/object:Gem::Version
|
|
138
|
-
version: 2.7.6
|
|
139
|
-
- !ruby/object:Gem::Dependency
|
|
140
|
-
name: foreman
|
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - ">="
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: '0'
|
|
146
|
-
type: :development
|
|
147
|
-
prerelease: false
|
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
-
requirements:
|
|
150
|
-
- - ">="
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: '0'
|
|
153
|
-
- !ruby/object:Gem::Dependency
|
|
154
|
-
name: gem-release
|
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
|
156
|
-
requirements:
|
|
157
|
-
- - ">="
|
|
158
|
-
- !ruby/object:Gem::Version
|
|
159
|
-
version: '0'
|
|
160
|
-
type: :development
|
|
161
|
-
prerelease: false
|
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
-
requirements:
|
|
164
|
-
- - ">="
|
|
165
|
-
- !ruby/object:Gem::Version
|
|
166
|
-
version: '0'
|
|
167
|
-
- !ruby/object:Gem::Dependency
|
|
168
|
-
name: github_changelog_generator
|
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
|
170
|
-
requirements:
|
|
171
|
-
- - ">="
|
|
172
|
-
- !ruby/object:Gem::Version
|
|
173
|
-
version: '0'
|
|
174
|
-
type: :development
|
|
175
|
-
prerelease: false
|
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
-
requirements:
|
|
178
|
-
- - ">="
|
|
179
|
-
- !ruby/object:Gem::Version
|
|
180
|
-
version: '0'
|
|
181
125
|
- !ruby/object:Gem::Dependency
|
|
182
126
|
name: kramdown
|
|
183
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -408,6 +352,7 @@ files:
|
|
|
408
352
|
- lib/good_job/adapter.rb
|
|
409
353
|
- lib/good_job/assignable_connection.rb
|
|
410
354
|
- lib/good_job/bulk.rb
|
|
355
|
+
- lib/good_job/callable.rb
|
|
411
356
|
- lib/good_job/capsule.rb
|
|
412
357
|
- lib/good_job/cleanup_tracker.rb
|
|
413
358
|
- lib/good_job/cli.rb
|