good_job 3.18.1 → 3.18.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2573770a9539b895705eee99e074ec34cc74a1b2fffc491c6b01fe2218792bf3
4
- data.tar.gz: 49ae57e1ccfd0cf54421c349b1e0659dab195530f89ecce2bd6f29c37315e86d
3
+ metadata.gz: 930bb77e947ac155ee655210ab15ef32ac40fc2d6487eaf80b0005d7e5675156
4
+ data.tar.gz: b3e26f0b7f4d60483a6d0646d5797654e447542b8d6cb9eca22e2cb7cbfaac78
5
5
  SHA512:
6
- metadata.gz: aa1cdc0760d2d139acd4f76d95aab2093480930dd04b1a93673510497abb0f5d589ff1d71741d4e6f940d0c983bb003cbadeb06d9702a7b1165ba0f45bb13a47
7
- data.tar.gz: 7184e6f9816441a85d2d2574482fbb36ea39a3c0f76bb9a5169df9ee7ad63e7a5f150f110087eba9938bfc87af79745c4a9427391906a04457ed1993b7c2f6f2
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)
@@ -16,7 +16,7 @@ module GoodJob
16
16
  end
17
17
 
18
18
  def default_base_query
19
- GoodJob::BatchRecord.all.includes(:jobs)
19
+ GoodJob::BatchRecord.includes(:jobs)
20
20
  end
21
21
  end
22
22
  end
@@ -59,6 +59,10 @@ module GoodJob
59
59
  end
60
60
  end
61
61
 
62
+ def self.primary_key
63
+ :id
64
+ end
65
+
62
66
  def self.find(id)
63
67
  new _record: BatchRecord.find(id)
64
68
  end
@@ -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 || last_at) }
64
- return Fugit.parse(result).next_time.to_t if result.is_a?(String)
65
-
66
- return result
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: schedule,
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 Proc
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.schedule %></span>
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.last_at), cron_entry_path(cron_entry), title: "Job #{cron_entry.last_job.id}" %>
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
@@ -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::AtomicBoolean.new(false)
73
- @listening = Concurrent::AtomicBoolean.new(false)
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
- @connected.true?
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
- @listening.true?
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.make_false
118
- @listening.make_false
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.make_true
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.make_false
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?(&:listening?)
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"]]
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GoodJob
4
4
  # GoodJob gem version.
5
- VERSION = '3.18.1'
5
+ VERSION = '3.18.3'
6
6
 
7
7
  # GoodJob version as Gem::Version object
8
8
  GEM_VERSION = Gem::Version.new(VERSION)
data/lib/good_job.rb CHANGED
@@ -16,6 +16,7 @@ require "good_job/active_job_extensions/notify_options"
16
16
 
17
17
  require "good_job/assignable_connection"
18
18
  require "good_job/bulk"
19
+ require "good_job/callable"
19
20
  require "good_job/capsule"
20
21
  require "good_job/cleanup_tracker"
21
22
  require "good_job/cli"
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.1
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-08-30 00:00:00.000000000 Z
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