good_job 4.3.0 → 4.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +42 -0
- data/README.md +5 -0
- data/app/models/concerns/good_job/filterable.rb +1 -1
- data/app/models/good_job/cron_entry.rb +13 -0
- data/app/models/good_job/job.rb +1 -1
- data/app/models/good_job/setting.rb +8 -6
- data/lib/good_job/active_job_extensions/labels.rb +1 -1
- data/lib/good_job/configuration.rb +6 -0
- data/lib/good_job/cron_manager.rb +22 -1
- data/lib/good_job/version.rb +1 -1
- 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: 68dae79a3d669ccfd101719015e70aee8b54230c339012351ad677862732dc70
|
4
|
+
data.tar.gz: d1242d0a898eff92aa4492d174de9cc73b0e610c5b1f56e358a304a864e39493
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bac343036b068fa03559d168346c37e41b110e4e9e902af8c58209880afdf75e44301ea845aca208ba583245fd4f2aa486d80b0905492e830501851b5190bd8
|
7
|
+
data.tar.gz: 576f825db2e84ae3ae3e19ccdf3e3a7becd2db81fb1960ebd26f18aa0779224ec4e79b0a976cd256cc0e19303e3b53d88b41f10be6a405ce284a731dd99654b4
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,47 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v4.4.1](https://github.com/bensheldon/good_job/tree/v4.4.1) (2024-10-10)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v4.4.0...v4.4.1)
|
6
|
+
|
7
|
+
**Fixed bugs:**
|
8
|
+
|
9
|
+
- Better search job arguments \(including integers\) by adding `serialized_params->>arguments` explicitly [\#1504](https://github.com/bensheldon/good_job/pull/1504) ([bensheldon](https://github.com/bensheldon))
|
10
|
+
|
11
|
+
**Closed issues:**
|
12
|
+
|
13
|
+
- Searching for an integer type argument \(on the dashboard\) does not yeild any results [\#1458](https://github.com/bensheldon/good_job/issues/1458)
|
14
|
+
|
15
|
+
**Merged pull requests:**
|
16
|
+
|
17
|
+
- Clean up appraisals, add rails 8, use postgres 17 [\#1505](https://github.com/bensheldon/good_job/pull/1505) ([Earlopain](https://github.com/Earlopain))
|
18
|
+
- Bump the bundler-lint group across 1 directory with 5 updates [\#1501](https://github.com/bensheldon/good_job/pull/1501) ([dependabot[bot]](https://github.com/apps/dependabot))
|
19
|
+
|
20
|
+
## [v4.4.0](https://github.com/bensheldon/good_job/tree/v4.4.0) (2024-10-08)
|
21
|
+
|
22
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v4.3.0...v4.4.0)
|
23
|
+
|
24
|
+
**Fixed bugs:**
|
25
|
+
|
26
|
+
- fix: unable to use keyword args when including the `Labels` extension [\#1500](https://github.com/bensheldon/good_job/pull/1500) ([ElMassimo](https://github.com/ElMassimo))
|
27
|
+
- Fix GoodJob::Setting duplicate keys [\#1498](https://github.com/bensheldon/good_job/pull/1498) ([mohammednasser-32](https://github.com/mohammednasser-32))
|
28
|
+
- Allow `GoodJob::Job#retry_job`'s transaction to be joinable \(fix CI for current `rails-head`\) [\#1496](https://github.com/bensheldon/good_job/pull/1496) ([Earlopain](https://github.com/Earlopain))
|
29
|
+
|
30
|
+
**Closed issues:**
|
31
|
+
|
32
|
+
- Inline adapter doesn't retry jobs that throw a retryable error [\#1497](https://github.com/bensheldon/good_job/issues/1497)
|
33
|
+
- scheduled\_at not respecting given timezone [\#1491](https://github.com/bensheldon/good_job/issues/1491)
|
34
|
+
- Multiple same values in cron\_keys\_disabled, cron\_keys\_enabled in good\_job\_settings table [\#1490](https://github.com/bensheldon/good_job/issues/1490)
|
35
|
+
- Cron jobs can be missed if deploys are timed just right [\#1484](https://github.com/bensheldon/good_job/issues/1484)
|
36
|
+
- Configuring connection pool in external mode [\#1483](https://github.com/bensheldon/good_job/issues/1483)
|
37
|
+
- GoodJob Timezone Day Light Savings [\#1480](https://github.com/bensheldon/good_job/issues/1480)
|
38
|
+
- Unable to use labels with kwargs in job initializer [\#1350](https://github.com/bensheldon/good_job/issues/1350)
|
39
|
+
|
40
|
+
**Merged pull requests:**
|
41
|
+
|
42
|
+
- Bump puma from 6.4.2 to 6.4.3 [\#1492](https://github.com/bensheldon/good_job/pull/1492) ([dependabot[bot]](https://github.com/apps/dependabot))
|
43
|
+
- Add `cron_graceful_restart_period` to avoid missing recurring jobs that occurred during deployment downtime [\#1488](https://github.com/bensheldon/good_job/pull/1488) ([bensheldon](https://github.com/bensheldon))
|
44
|
+
|
3
45
|
## [v4.3.0](https://github.com/bensheldon/good_job/tree/v4.3.0) (2024-09-14)
|
4
46
|
|
5
47
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v4.2.1...v4.3.0)
|
data/README.md
CHANGED
@@ -257,6 +257,7 @@ Rails.application.configure do
|
|
257
257
|
config.good_job.shutdown_timeout = 25 # seconds
|
258
258
|
config.good_job.enable_cron = true
|
259
259
|
config.good_job.cron = { example: { cron: '0 * * * *', class: 'ExampleJob' } }
|
260
|
+
config.good_job.cron_graceful_restart_period = 5.minutes
|
260
261
|
config.good_job.dashboard_default_locale = :en
|
261
262
|
|
262
263
|
# ...or all at once.
|
@@ -298,6 +299,7 @@ Available configuration options are:
|
|
298
299
|
- `max_cache` (integer) sets the maximum number of scheduled jobs that will be stored in memory to reduce execution latency when also polling for scheduled jobs. Caching 10,000 scheduled jobs uses approximately 20MB of memory. You can also set this with the environment variable `GOOD_JOB_MAX_CACHE`.
|
299
300
|
- `shutdown_timeout` (integer) number of seconds to wait for jobs to finish when shutting down before stopping the thread. Defaults to forever: `-1`. You can also set this with the environment variable `GOOD_JOB_SHUTDOWN_TIMEOUT`.
|
300
301
|
- `enable_cron` (boolean) whether to run cron process. Defaults to `false`. You can also set this with the environment variable `GOOD_JOB_ENABLE_CRON`.
|
302
|
+
- `cron_graceful_restart_period` (integer) when restarting cron, attempt to re-enqueue jobs that would have been enqueued by cron within this time period (e.g. `1.minute`). This should match the expected downtime during deploys.
|
301
303
|
- `enable_listen_notify` (boolean) whether to enqueue and read jobs with Postgres LISTEN/NOTIFY. Defaults to `true`. You can also set this with the environment variable `GOOD_JOB_ENABLE_LISTEN_NOTIFY`.
|
302
304
|
- `cron` (hash) cron configuration. Defaults to `{}`. You can also set this as a JSON string with the environment variable `GOOD_JOB_CRON`
|
303
305
|
- `cleanup_discarded_jobs` (boolean) whether to destroy discarded jobs when cleaning up preserved jobs using the `$ good_job cleanup_preserved_jobs` CLI command or calling `GoodJob.cleanup_preserved_jobs`. Defaults to `true`. Can also be set with the environment variable `GOOD_JOB_CLEANUP_DISCARDED_JOBS`. _This configuration is only used when {GoodJob.preserve_job_records} is `true`._
|
@@ -625,6 +627,9 @@ If you use the [Dashboard](#dashboard) the scheduled tasks can be viewed in the
|
|
625
627
|
# Enable cron enqueuing in this process
|
626
628
|
config.good_job.enable_cron = true
|
627
629
|
|
630
|
+
# Without zero-downtime deploys, re-attempt previous schedules after a deploy
|
631
|
+
config.good_job.cron_graceful_restart_period = 1.minute
|
632
|
+
|
628
633
|
# Configure cron with a hash that has a unique key for each recurring job
|
629
634
|
config.good_job.cron = {
|
630
635
|
# Every 15 minutes, enqueue `ExampleJob.set(priority: -10).perform_later(42, "life", name: "Alice")`
|
@@ -35,7 +35,7 @@ module GoodJob
|
|
35
35
|
next if query.blank?
|
36
36
|
|
37
37
|
# TODO: turn this into proper bind parameters in Arel
|
38
|
-
tsvector = "(to_tsvector('english', id::text) || to_tsvector('english', COALESCE(active_job_id::text, '')) || to_tsvector('english', serialized_params) || to_tsvector('english', COALESCE(error, '')) || to_tsvector('english', COALESCE(array_to_string(labels, ' '), '')))"
|
38
|
+
tsvector = "(to_tsvector('english', id::text) || to_tsvector('english', COALESCE(active_job_id::text, '')) || to_tsvector('english', serialized_params) || to_tsvector('english', COALESCE(serialized_params->>'arguments', '')) || to_tsvector('english', COALESCE(error, '')) || to_tsvector('english', COALESCE(array_to_string(labels, ' '), '')))"
|
39
39
|
to_tsquery_function = database_supports_websearch_to_tsquery? ? 'websearch_to_tsquery' : 'plainto_tsquery'
|
40
40
|
where("#{tsvector} @@ #{to_tsquery_function}(?)", query)
|
41
41
|
.order(sanitize_sql_for_order([Arel.sql("ts_rank(#{tsvector}, #{to_tsquery_function}(?))"), query]) => 'DESC')
|
@@ -71,6 +71,19 @@ module GoodJob # :nodoc:
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
def within(period, previously_at: nil)
|
75
|
+
if cron_proc?
|
76
|
+
result = Rails.application.executor.wrap { cron.call(previously_at || last_job_at) }
|
77
|
+
if result.is_a?(String)
|
78
|
+
Fugit.parse(result).within(period).map(&:to_t)
|
79
|
+
else
|
80
|
+
result
|
81
|
+
end
|
82
|
+
else
|
83
|
+
fugit.within(period).map(&:to_t)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
74
87
|
def enabled?
|
75
88
|
GoodJob::Setting.cron_key_enabled?(key, default: enabled_by_default?)
|
76
89
|
end
|
data/app/models/good_job/job.rb
CHANGED
@@ -478,7 +478,7 @@ module GoodJob
|
|
478
478
|
current_thread.job = self
|
479
479
|
current_thread.retry_now = true
|
480
480
|
|
481
|
-
|
481
|
+
transaction do
|
482
482
|
new_active_job = active_job.retry_job(wait: 0, error: error)
|
483
483
|
self.error_event = :retried if error
|
484
484
|
save!
|
@@ -19,30 +19,32 @@ module GoodJob
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.cron_key_enable(key)
|
22
|
+
key_string = key.to_s
|
22
23
|
enabled_setting = find_or_initialize_by(key: CRON_KEYS_ENABLED) do |record|
|
23
24
|
record.value = []
|
24
25
|
end
|
25
|
-
enabled_setting.value << key unless enabled_setting.value.include?(
|
26
|
+
enabled_setting.value << key unless enabled_setting.value.include?(key_string)
|
26
27
|
enabled_setting.save!
|
27
28
|
|
28
29
|
disabled_setting = GoodJob::Setting.find_by(key: CRON_KEYS_DISABLED)
|
29
|
-
return unless disabled_setting&.value&.include?(
|
30
|
+
return unless disabled_setting&.value&.include?(key_string)
|
30
31
|
|
31
|
-
disabled_setting.value.delete(
|
32
|
+
disabled_setting.value.delete(key_string)
|
32
33
|
disabled_setting.save!
|
33
34
|
end
|
34
35
|
|
35
36
|
def self.cron_key_disable(key)
|
36
37
|
enabled_setting = GoodJob::Setting.find_by(key: CRON_KEYS_ENABLED)
|
37
|
-
|
38
|
-
|
38
|
+
key_string = key.to_s
|
39
|
+
if enabled_setting&.value&.include?(key_string)
|
40
|
+
enabled_setting.value.delete(key_string)
|
39
41
|
enabled_setting.save!
|
40
42
|
end
|
41
43
|
|
42
44
|
disabled_setting = find_or_initialize_by(key: CRON_KEYS_DISABLED) do |record|
|
43
45
|
record.value = []
|
44
46
|
end
|
45
|
-
disabled_setting.value << key unless disabled_setting.value.include?(
|
47
|
+
disabled_setting.value << key unless disabled_setting.value.include?(key_string)
|
46
48
|
disabled_setting.save!
|
47
49
|
end
|
48
50
|
end
|
@@ -219,6 +219,12 @@ module GoodJob
|
|
219
219
|
cron.map { |cron_key, params| GoodJob::CronEntry.new(params.merge(key: cron_key)) }
|
220
220
|
end
|
221
221
|
|
222
|
+
def cron_graceful_restart_period
|
223
|
+
options[:cron_graceful_restart_period] ||
|
224
|
+
rails_config[:cron_graceful_restart_period] ||
|
225
|
+
env['GOOD_JOB_CRON_GRACEFUL_RESTART_PERIOD']
|
226
|
+
end
|
227
|
+
|
222
228
|
# The number of queued jobs to select when polling for a job to run.
|
223
229
|
# This limit is intended to avoid locking a large number of rows when selecting eligible jobs
|
224
230
|
# from the queue. This value should be higher than the total number of threads across all good_job
|
@@ -31,11 +31,12 @@ module GoodJob # :nodoc:
|
|
31
31
|
|
32
32
|
# @param cron_entries [Array<CronEntry>]
|
33
33
|
# @param start_on_initialize [Boolean]
|
34
|
-
def initialize(cron_entries = [], start_on_initialize: false, executor: Concurrent.global_io_executor)
|
34
|
+
def initialize(cron_entries = [], start_on_initialize: false, graceful_restart_period: nil, executor: Concurrent.global_io_executor)
|
35
35
|
@executor = executor
|
36
36
|
@running = false
|
37
37
|
@cron_entries = cron_entries
|
38
38
|
@tasks = Concurrent::Hash.new
|
39
|
+
@graceful_restart_period = graceful_restart_period
|
39
40
|
|
40
41
|
start if start_on_initialize
|
41
42
|
self.class.instances << self
|
@@ -47,6 +48,7 @@ module GoodJob # :nodoc:
|
|
47
48
|
@running = true
|
48
49
|
cron_entries.each do |cron_entry|
|
49
50
|
create_task(cron_entry)
|
51
|
+
create_graceful_tasks(cron_entry) if @graceful_restart_period
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
@@ -97,5 +99,24 @@ module GoodJob # :nodoc:
|
|
97
99
|
future.add_observer(self.class, :task_observer)
|
98
100
|
future.execute
|
99
101
|
end
|
102
|
+
|
103
|
+
# Uses the graceful restart period to re-enqueue jobs that were scheduled to run during the period.
|
104
|
+
# The existing uniqueness logic should ensure this does not create duplicate jobs.
|
105
|
+
# @param cron_entry [CronEntry] the CronEntry object to schedule
|
106
|
+
def create_graceful_tasks(cron_entry)
|
107
|
+
return unless @graceful_restart_period
|
108
|
+
|
109
|
+
time_period = @graceful_restart_period.ago..Time.current
|
110
|
+
cron_entry.within(time_period).each do |cron_at|
|
111
|
+
future = Concurrent::Future.new(args: [self, cron_entry, cron_at], executor: @executor) do |_thr_scheduler, thr_cron_entry, thr_cron_at|
|
112
|
+
Rails.application.executor.wrap do
|
113
|
+
cron_entry.enqueue(thr_cron_at) if thr_cron_entry.enabled?
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
future.add_observer(self.class, :task_observer)
|
118
|
+
future.execute
|
119
|
+
end
|
120
|
+
end
|
100
121
|
end
|
101
122
|
end
|
data/lib/good_job/version.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: 4.
|
4
|
+
version: 4.4.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-
|
11
|
+
date: 2024-10-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|