good_job 3.17.4 → 3.18.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 +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +4 -0
- data/app/models/good_job/cron_entry.rb +25 -19
- data/lib/good_job/adapter.rb +2 -17
- data/lib/good_job/configuration.rb +30 -11
- data/lib/good_job/cron_manager.rb +4 -3
- data/lib/good_job/version.rb +1 -1
- data/lib/good_job.rb +2 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2573770a9539b895705eee99e074ec34cc74a1b2fffc491c6b01fe2218792bf3
|
|
4
|
+
data.tar.gz: 49ae57e1ccfd0cf54421c349b1e0659dab195530f89ecce2bd6f29c37315e86d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa1cdc0760d2d139acd4f76d95aab2093480930dd04b1a93673510497abb0f5d589ff1d71741d4e6f940d0c983bb003cbadeb06d9702a7b1165ba0f45bb13a47
|
|
7
|
+
data.tar.gz: 7184e6f9816441a85d2d2574482fbb36ea39a3c0f76bb9a5169df9ee7ad63e7a5f150f110087eba9938bfc87af79745c4a9427391906a04457ed1993b7c2f6f2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v3.18.1](https://github.com/bensheldon/good_job/tree/v3.18.1) (2023-08-30)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.18.0...v3.18.1)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- Respect the configured execution mode, even within the CLI [\#1056](https://github.com/bensheldon/good_job/pull/1056) ([bensheldon](https://github.com/bensheldon))
|
|
10
|
+
|
|
11
|
+
**Closed issues:**
|
|
12
|
+
|
|
13
|
+
- Bug: calling `GoodJob.restart` in Puma on\_worker\_boot starts GoodJob regardless of it being in async mode or not [\#1054](https://github.com/bensheldon/good_job/issues/1054)
|
|
14
|
+
- \[Feature Request?\] Config Option to Inline Child-Jobs in Worker Processes [\#1052](https://github.com/bensheldon/good_job/issues/1052)
|
|
15
|
+
- \[Feature Request\] Hook to extend cron schedules [\#1050](https://github.com/bensheldon/good_job/issues/1050)
|
|
16
|
+
|
|
17
|
+
**Merged pull requests:**
|
|
18
|
+
|
|
19
|
+
- `GoodJob.restart` should not start capsules \(job execution\) when in a webserver but not in async mode [\#1055](https://github.com/bensheldon/good_job/pull/1055) ([bensheldon](https://github.com/bensheldon))
|
|
20
|
+
|
|
21
|
+
## [v3.18.0](https://github.com/bensheldon/good_job/tree/v3.18.0) (2023-08-30)
|
|
22
|
+
|
|
23
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.17.4...v3.18.0)
|
|
24
|
+
|
|
25
|
+
**Implemented enhancements:**
|
|
26
|
+
|
|
27
|
+
- Support configuring cron schedule dynamically with a block [\#1051](https://github.com/bensheldon/good_job/pull/1051) ([DanielHeath](https://github.com/DanielHeath))
|
|
28
|
+
|
|
3
29
|
## [v3.17.4](https://github.com/bensheldon/good_job/tree/v3.17.4) (2023-08-24)
|
|
4
30
|
|
|
5
31
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.17.3...v3.17.4)
|
data/README.md
CHANGED
|
@@ -504,6 +504,10 @@ config.good_job.cron = {
|
|
|
504
504
|
cron: "0 0,12 * * *",
|
|
505
505
|
class: "AnotherJob",
|
|
506
506
|
},
|
|
507
|
+
complex_schedule: {
|
|
508
|
+
class: "ComplexScheduleJob",
|
|
509
|
+
cron: -> (last_ran) { (last_ran.blank? ? Time.now : last_ran + 14.hours).at_beginning_of_minute }
|
|
510
|
+
}
|
|
507
511
|
# etc.
|
|
508
512
|
}
|
|
509
513
|
```
|
|
@@ -27,6 +27,7 @@ module GoodJob # :nodoc:
|
|
|
27
27
|
def initialize(params = {})
|
|
28
28
|
@params = params
|
|
29
29
|
|
|
30
|
+
return if cron_proc?
|
|
30
31
|
raise ArgumentError, "Invalid cron format: '#{cron}'" unless fugit.instance_of?(Fugit::Cron)
|
|
31
32
|
end
|
|
32
33
|
|
|
@@ -41,10 +42,6 @@ module GoodJob # :nodoc:
|
|
|
41
42
|
params.fetch(:class)
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
def cron
|
|
45
|
-
params.fetch(:cron)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
45
|
def set
|
|
49
46
|
params[:set]
|
|
50
47
|
end
|
|
@@ -61,16 +58,21 @@ module GoodJob # :nodoc:
|
|
|
61
58
|
params[:description]
|
|
62
59
|
end
|
|
63
60
|
|
|
64
|
-
def next_at
|
|
61
|
+
def next_at(previously_at: nil)
|
|
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
|
+
|
|
68
|
+
end
|
|
65
69
|
fugit.next_time.to_t
|
|
66
70
|
end
|
|
67
71
|
|
|
68
72
|
def schedule
|
|
69
|
-
|
|
70
|
-
end
|
|
73
|
+
return "Custom schedule" if cron_proc?
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
@_fugit ||= Fugit.parse(cron)
|
|
75
|
+
fugit.original
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
def jobs
|
|
@@ -80,11 +82,7 @@ module GoodJob # :nodoc:
|
|
|
80
82
|
def last_at
|
|
81
83
|
return if last_job.blank?
|
|
82
84
|
|
|
83
|
-
|
|
84
|
-
(last_job.cron_at || last_job.created_at).localtime
|
|
85
|
-
else
|
|
86
|
-
last_job.created_at
|
|
87
|
-
end
|
|
85
|
+
(last_job.cron_at || last_job.created_at).localtime
|
|
88
86
|
end
|
|
89
87
|
|
|
90
88
|
def enabled?
|
|
@@ -116,11 +114,7 @@ module GoodJob # :nodoc:
|
|
|
116
114
|
end
|
|
117
115
|
|
|
118
116
|
def last_job
|
|
119
|
-
|
|
120
|
-
jobs.order("cron_at DESC NULLS LAST").first
|
|
121
|
-
else
|
|
122
|
-
jobs.order(created_at: :asc).last
|
|
123
|
-
end
|
|
117
|
+
jobs.order("cron_at DESC NULLS LAST").first
|
|
124
118
|
end
|
|
125
119
|
|
|
126
120
|
def display_properties
|
|
@@ -138,6 +132,18 @@ module GoodJob # :nodoc:
|
|
|
138
132
|
|
|
139
133
|
private
|
|
140
134
|
|
|
135
|
+
def cron
|
|
136
|
+
params.fetch(:cron)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def cron_proc?
|
|
140
|
+
cron.respond_to?(:call)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def fugit
|
|
144
|
+
@_fugit ||= Fugit.parse(cron)
|
|
145
|
+
end
|
|
146
|
+
|
|
141
147
|
def set_value
|
|
142
148
|
value = set || {}
|
|
143
149
|
value.respond_to?(:call) ? value.call : value
|
data/lib/good_job/adapter.rb
CHANGED
|
@@ -185,7 +185,7 @@ module GoodJob
|
|
|
185
185
|
# @return [Boolean]
|
|
186
186
|
def execute_async?
|
|
187
187
|
execution_mode == :async_all ||
|
|
188
|
-
(execution_mode.in?([:async, :async_server]) &&
|
|
188
|
+
(execution_mode.in?([:async, :async_server]) && GoodJob.configuration.in_webserver?)
|
|
189
189
|
end
|
|
190
190
|
|
|
191
191
|
# Whether in +:external+ execution mode.
|
|
@@ -193,7 +193,7 @@ module GoodJob
|
|
|
193
193
|
def execute_externally?
|
|
194
194
|
execution_mode.nil? ||
|
|
195
195
|
execution_mode == :external ||
|
|
196
|
-
(execution_mode.in?([:async, :async_server]) && !
|
|
196
|
+
(execution_mode.in?([:async, :async_server]) && !GoodJob.configuration.in_webserver?)
|
|
197
197
|
end
|
|
198
198
|
|
|
199
199
|
# Whether in +:inline+ execution mode.
|
|
@@ -219,21 +219,6 @@ module GoodJob
|
|
|
219
219
|
|
|
220
220
|
private
|
|
221
221
|
|
|
222
|
-
# Whether running in a web server process.
|
|
223
|
-
# @return [Boolean, nil]
|
|
224
|
-
def in_server_process?
|
|
225
|
-
return @_in_server_process if defined? @_in_server_process
|
|
226
|
-
|
|
227
|
-
@_in_server_process = Rails.const_defined?(:Server) || begin
|
|
228
|
-
self_caller = caller
|
|
229
|
-
|
|
230
|
-
self_caller.grep(%r{config.ru}).any? || # EXAMPLE: config.ru:3:in `block in <main>' OR config.ru:3:in `new_from_string'
|
|
231
|
-
self_caller.grep(%r{puma/request}).any? || # EXAMPLE: puma-5.6.4/lib/puma/request.rb:76:in `handle_request'
|
|
232
|
-
self_caller.grep(%{/rack/handler/}).any? || # EXAMPLE: iodine-0.7.44/lib/rack/handler/iodine.rb:13:in `start'
|
|
233
|
-
(Concurrent.on_jruby? && self_caller.grep(%r{jruby/rack/rails_booter}).any?) # EXAMPLE: uri:classloader:/jruby/rack/rails_booter.rb:83:in `load_environment'
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
|
|
237
222
|
def send_notify?(active_job)
|
|
238
223
|
return false unless GoodJob.configuration.enable_listen_notify
|
|
239
224
|
return true unless active_job.respond_to?(:good_job_notify)
|
|
@@ -79,6 +79,8 @@ module GoodJob
|
|
|
79
79
|
def initialize(options, env: ENV)
|
|
80
80
|
@options = options
|
|
81
81
|
@env = env
|
|
82
|
+
|
|
83
|
+
@_in_webserver = nil
|
|
82
84
|
end
|
|
83
85
|
|
|
84
86
|
def validate!
|
|
@@ -89,21 +91,24 @@ module GoodJob
|
|
|
89
91
|
# for more details on possible values.
|
|
90
92
|
# @return [Symbol]
|
|
91
93
|
def execution_mode
|
|
92
|
-
mode =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
rails_config[:execution_mode] ||
|
|
97
|
-
env['GOOD_JOB_EXECUTION_MODE']
|
|
98
|
-
end
|
|
94
|
+
mode = options[:execution_mode] ||
|
|
95
|
+
rails_config[:execution_mode] ||
|
|
96
|
+
env['GOOD_JOB_EXECUTION_MODE']
|
|
97
|
+
mode = mode.to_sym if mode
|
|
99
98
|
|
|
100
99
|
if mode
|
|
101
|
-
mode
|
|
100
|
+
if GoodJob::CLI.within_exe? && [:async, :async_server].include?(mode)
|
|
101
|
+
:external
|
|
102
|
+
else
|
|
103
|
+
mode
|
|
104
|
+
end
|
|
105
|
+
elsif GoodJob::CLI.within_exe?
|
|
106
|
+
:external
|
|
102
107
|
elsif Rails.env.development?
|
|
103
108
|
:async
|
|
104
109
|
elsif Rails.env.test?
|
|
105
110
|
:inline
|
|
106
|
-
else
|
|
111
|
+
else # rubocop:disable Lint/DuplicateBranch
|
|
107
112
|
:external
|
|
108
113
|
end
|
|
109
114
|
end
|
|
@@ -173,7 +178,7 @@ module GoodJob
|
|
|
173
178
|
|
|
174
179
|
# The number of seconds to wait for jobs to finish when shutting down
|
|
175
180
|
# before stopping the thread. +-1+ is forever.
|
|
176
|
-
# @return [
|
|
181
|
+
# @return [Float]
|
|
177
182
|
def shutdown_timeout
|
|
178
183
|
(
|
|
179
184
|
options[:shutdown_timeout] ||
|
|
@@ -245,7 +250,7 @@ module GoodJob
|
|
|
245
250
|
|
|
246
251
|
# Number of jobs a {Scheduler} will execute before automatically cleaning up preserved jobs.
|
|
247
252
|
# Positive values will clean up after that many jobs have run, false or 0 will disable, and -1 will clean up after every job.
|
|
248
|
-
# @return [Integer, nil]
|
|
253
|
+
# @return [Integer, Boolean, nil]
|
|
249
254
|
def cleanup_interval_jobs
|
|
250
255
|
if rails_config.key?(:cleanup_interval_jobs)
|
|
251
256
|
value = rails_config[:cleanup_interval_jobs]
|
|
@@ -349,6 +354,20 @@ module GoodJob
|
|
|
349
354
|
rails_config[:dashboard_default_locale] || DEFAULT_DASHBOARD_DEFAULT_LOCALE
|
|
350
355
|
end
|
|
351
356
|
|
|
357
|
+
# Whether running in a web server process.
|
|
358
|
+
# @return [Boolean, nil]
|
|
359
|
+
def in_webserver?
|
|
360
|
+
return @_in_webserver unless @_in_webserver.nil?
|
|
361
|
+
|
|
362
|
+
@_in_webserver = Rails.const_defined?(:Server) || begin
|
|
363
|
+
self_caller = caller
|
|
364
|
+
self_caller.grep(%r{config.ru}).any? || # EXAMPLE: config.ru:3:in `block in <main>' OR config.ru:3:in `new_from_string'
|
|
365
|
+
self_caller.grep(%r{puma/request}).any? || # EXAMPLE: puma-5.6.4/lib/puma/request.rb:76:in `handle_request'
|
|
366
|
+
self_caller.grep(%{/rack/handler/}).any? || # EXAMPLE: iodine-0.7.44/lib/rack/handler/iodine.rb:13:in `start'
|
|
367
|
+
(Concurrent.on_jruby? && self_caller.grep(%r{jruby/rack/rails_booter}).any?) # EXAMPLE: uri:classloader:/jruby/rack/rails_booter.rb:83:in `load_environment'
|
|
368
|
+
end || false
|
|
369
|
+
end
|
|
370
|
+
|
|
352
371
|
private
|
|
353
372
|
|
|
354
373
|
def rails_config
|
|
@@ -82,12 +82,13 @@ module GoodJob # :nodoc:
|
|
|
82
82
|
|
|
83
83
|
# Enqueues a scheduled task
|
|
84
84
|
# @param cron_entry [CronEntry] the CronEntry object to schedule
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
# @param previously_at [Date, Time, ActiveSupport::TimeWithZone, nil] the last, +in-memory+, scheduled time the cron task was intended to run
|
|
86
|
+
def create_task(cron_entry, previously_at: nil)
|
|
87
|
+
cron_at = cron_entry.next_at(previously_at: previously_at)
|
|
87
88
|
delay = [(cron_at - Time.current).to_f, 0].max
|
|
88
89
|
future = Concurrent::ScheduledTask.new(delay, args: [self, cron_entry, cron_at], executor: @executor) do |thr_scheduler, thr_cron_entry, thr_cron_at|
|
|
89
90
|
# Re-schedule the next cron task before executing the current task
|
|
90
|
-
thr_scheduler.create_task(thr_cron_entry)
|
|
91
|
+
thr_scheduler.create_task(thr_cron_entry, previously_at: thr_cron_at)
|
|
91
92
|
|
|
92
93
|
Rails.application.executor.wrap do
|
|
93
94
|
cron_entry.enqueue(thr_cron_at) if thr_cron_entry.enabled?
|
data/lib/good_job/version.rb
CHANGED
data/lib/good_job.rb
CHANGED
|
@@ -151,6 +151,8 @@ module GoodJob
|
|
|
151
151
|
# @param timeout [Numeric] Seconds to wait for active threads to finish.
|
|
152
152
|
# @return [void]
|
|
153
153
|
def self.restart(timeout: -1)
|
|
154
|
+
return if configuration.execution_mode != :async && configuration.in_webserver?
|
|
155
|
+
|
|
154
156
|
_shutdown_all(Capsule.instances, :restart, timeout: timeout)
|
|
155
157
|
end
|
|
156
158
|
|
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.18.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: 2023-08-
|
|
11
|
+
date: 2023-08-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activejob
|