good_job 3.7.4 → 3.8.0
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 +32 -1
- data/app/controllers/good_job/jobs_controller.rb +1 -1
- data/app/models/good_job/execution.rb +1 -0
- data/app/models/good_job/lockable.rb +1 -0
- data/config/locales/fr.yml +83 -0
- data/lib/good_job/active_job_extensions/concurrency.rb +11 -10
- data/lib/good_job/job_performer.rb +9 -1
- data/lib/good_job/log_subscriber.rb +13 -0
- data/lib/good_job/scheduler.rb +5 -1
- data/lib/good_job/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d5d0c455a8d5d8f18fda38f1f9f126cc406250d188ee313d0352717c829cd126
|
|
4
|
+
data.tar.gz: 208b61ec3b48a7973b160093100b216eafbb96eee604e5e7edc2e7fb67bedfba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cac4f2c135e6c01cbdd6cd58c591d726ee8fbb66e623e3d1ed8bfb26e85e6b058e45bd60e3d2ba67b3133666df07d972db8eca75aa05df671b8284c01f45398f
|
|
7
|
+
data.tar.gz: 189ba8af30dc9e5a84c064090d5ede8a8f1da4bb56d2249f6ac4130ce3105c9c498f957ad05cf054f2697f83885570013c3c41ed5d197354c992b08518110656
|
data/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v3.8.0](https://github.com/bensheldon/good_job/tree/v3.8.0) (2023-01-27)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.7.4...v3.8.0)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- Capture and log ActiveJob IDs that are interrupted when Scheduler is forced to shutdown [\#794](https://github.com/bensheldon/good_job/pull/794) ([bensheldon](https://github.com/bensheldon))
|
|
10
|
+
|
|
11
|
+
**Fixed bugs:**
|
|
12
|
+
|
|
13
|
+
- Ensure Concurrency Keys are string-like and return a better error when they cannot be cast to a string [\#791](https://github.com/bensheldon/good_job/pull/791) ([Earlopain](https://github.com/Earlopain))
|
|
14
|
+
|
|
15
|
+
**Closed issues:**
|
|
16
|
+
|
|
17
|
+
- Work is not being picked up at the expected rate [\#802](https://github.com/bensheldon/good_job/issues/802)
|
|
18
|
+
- Cleaning up preserved jobs only removes a subset of the jobs [\#801](https://github.com/bensheldon/good_job/issues/801)
|
|
19
|
+
- Dashboard fails to execute JS on latest Firefox 108 [\#792](https://github.com/bensheldon/good_job/issues/792)
|
|
20
|
+
- Concurrency key doesn't handle Hash: TypeError \(can't cast Hash\) [\#784](https://github.com/bensheldon/good_job/issues/784)
|
|
21
|
+
|
|
22
|
+
**Merged pull requests:**
|
|
23
|
+
|
|
24
|
+
- Bump fugit from 1.8.0 to 1.8.1 [\#808](https://github.com/bensheldon/good_job/pull/808) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
25
|
+
- Bump rubocop-rspec from 2.17.1 to 2.18.1 [\#807](https://github.com/bensheldon/good_job/pull/807) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
26
|
+
- Bump globalid from 1.0.0 to 1.0.1 [\#804](https://github.com/bensheldon/good_job/pull/804) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
27
|
+
- Bump rack from 2.2.4 to 2.2.6.2 [\#803](https://github.com/bensheldon/good_job/pull/803) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
28
|
+
- Bump nokogiri from 1.13.10 to 1.14.0 [\#800](https://github.com/bensheldon/good_job/pull/800) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
29
|
+
- Bump rubocop from 1.42.0 to 1.43.0 [\#799](https://github.com/bensheldon/good_job/pull/799) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
30
|
+
- Bump rubocop-rspec from 2.16.0 to 2.17.1 [\#798](https://github.com/bensheldon/good_job/pull/798) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
31
|
+
- Add French translation [\#795](https://github.com/bensheldon/good_job/pull/795) ([francois-ferrandis](https://github.com/francois-ferrandis))
|
|
32
|
+
- Bump rubocop-rails from 2.17.3 to 2.17.4 [\#780](https://github.com/bensheldon/good_job/pull/780) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
33
|
+
|
|
3
34
|
## [v3.7.4](https://github.com/bensheldon/good_job/tree/v3.7.4) (2023-01-10)
|
|
4
35
|
|
|
5
36
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.7.3...v3.7.4)
|
|
6
37
|
|
|
7
|
-
**
|
|
38
|
+
**Fixed bugs:**
|
|
8
39
|
|
|
9
40
|
- Update to es-module-shims v1.6.3 and use an inline script entry-point; remove script.js entrypoint; remove sourcemap references [\#793](https://github.com/bensheldon/good_job/pull/793) ([bensheldon](https://github.com/bensheldon))
|
|
10
41
|
|
|
@@ -80,7 +80,7 @@ module GoodJob
|
|
|
80
80
|
def destroy
|
|
81
81
|
@job = Job.find(params[:id])
|
|
82
82
|
@job.destroy_job
|
|
83
|
-
redirect_to jobs_path, notice: "Job has been destroyed"
|
|
83
|
+
redirect_to jobs_path, notice: "Job has been destroyed"
|
|
84
84
|
end
|
|
85
85
|
|
|
86
86
|
private
|
|
@@ -193,6 +193,7 @@ module GoodJob
|
|
|
193
193
|
binds = [
|
|
194
194
|
ActiveRecord::Relation::QueryAttribute.new('key', key, ActiveRecord::Type::String.new),
|
|
195
195
|
]
|
|
196
|
+
|
|
196
197
|
locked = connection.exec_query(pg_or_jdbc_query(query), 'GoodJob::Lockable Advisory Lock', binds).first['locked']
|
|
197
198
|
return locked unless block_given?
|
|
198
199
|
return nil unless locked
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
fr:
|
|
3
|
+
datetime:
|
|
4
|
+
distance_in_words:
|
|
5
|
+
about_x_hours:
|
|
6
|
+
one: environ 1 heure
|
|
7
|
+
other: environ %{count} heures
|
|
8
|
+
about_x_months:
|
|
9
|
+
one: environ 1 heure
|
|
10
|
+
other: environ %{count} heures
|
|
11
|
+
about_x_years:
|
|
12
|
+
one: environ 1 an
|
|
13
|
+
other: environ %{count} ans
|
|
14
|
+
almost_x_years:
|
|
15
|
+
one: presque 1 an
|
|
16
|
+
other: presque %{count} ans
|
|
17
|
+
half_a_minute: une demi-minute
|
|
18
|
+
less_than_x_minutes:
|
|
19
|
+
one: moins d'une minute
|
|
20
|
+
other: moins de %{count} minutes
|
|
21
|
+
less_than_x_seconds:
|
|
22
|
+
one: moins d'une seconde
|
|
23
|
+
other: moins de %{count} secondes
|
|
24
|
+
over_x_years:
|
|
25
|
+
one: plus d'un an
|
|
26
|
+
other: plus de %{count} ans
|
|
27
|
+
x_days:
|
|
28
|
+
one: 1 jour
|
|
29
|
+
other: "%{count} jours"
|
|
30
|
+
x_minutes:
|
|
31
|
+
one: 1 minute
|
|
32
|
+
other: "%{count} minutes"
|
|
33
|
+
x_months:
|
|
34
|
+
one: 1 mois
|
|
35
|
+
other: "%{count} mois"
|
|
36
|
+
x_seconds:
|
|
37
|
+
one: 1 seconde
|
|
38
|
+
other: "%{count} secondes"
|
|
39
|
+
x_years:
|
|
40
|
+
one: 1 an
|
|
41
|
+
other: "%{count} ans"
|
|
42
|
+
duration:
|
|
43
|
+
hours: "%{hour}h %{min}m"
|
|
44
|
+
less_than_10_seconds: "%{sec}s"
|
|
45
|
+
milliseconds: "%{ms}ms"
|
|
46
|
+
minutes: "%{min}m %{sec}s"
|
|
47
|
+
seconds: "%{sec}s"
|
|
48
|
+
good_job:
|
|
49
|
+
shared:
|
|
50
|
+
footer:
|
|
51
|
+
last_update_html: Dernière mise à jour <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
|
52
|
+
wording: N'oublie pas, toi aussi tu fais du bon boulot !
|
|
53
|
+
navbar:
|
|
54
|
+
cron_schedules: Cron
|
|
55
|
+
jobs: Jobs
|
|
56
|
+
live_poll: En direct
|
|
57
|
+
name: "GoodJob 👍"
|
|
58
|
+
processes: Processus
|
|
59
|
+
status:
|
|
60
|
+
discarded: Abandonnés
|
|
61
|
+
queued: À la file
|
|
62
|
+
retried: Réessayés
|
|
63
|
+
running: En cours
|
|
64
|
+
scheduled: Programmés
|
|
65
|
+
succeeded: Réussis
|
|
66
|
+
number:
|
|
67
|
+
format:
|
|
68
|
+
delimiter: " "
|
|
69
|
+
separator: ","
|
|
70
|
+
human:
|
|
71
|
+
decimal_units:
|
|
72
|
+
format: "%n%u"
|
|
73
|
+
units:
|
|
74
|
+
billion: B
|
|
75
|
+
million: M
|
|
76
|
+
quadrillion: q
|
|
77
|
+
thousand: k
|
|
78
|
+
trillion: T
|
|
79
|
+
unit: ''
|
|
80
|
+
format:
|
|
81
|
+
delimiter: " "
|
|
82
|
+
precision: 3
|
|
83
|
+
separator: ","
|
|
@@ -4,6 +4,8 @@ module GoodJob
|
|
|
4
4
|
module Concurrency
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
6
|
|
|
7
|
+
VALID_TYPES = [String, Symbol, Numeric, Date, Time, TrueClass, FalseClass, NilClass].freeze
|
|
8
|
+
|
|
7
9
|
class ConcurrencyExceededError < StandardError
|
|
8
10
|
def backtrace
|
|
9
11
|
[] # suppress backtrace
|
|
@@ -30,6 +32,11 @@ module GoodJob
|
|
|
30
32
|
# Always allow jobs to be retried because the current job's execution will complete momentarily
|
|
31
33
|
next(block.call) if CurrentThread.active_job_id == job.job_id
|
|
32
34
|
|
|
35
|
+
# Only generate the concurrency key on the initial enqueue in case it is dynamic
|
|
36
|
+
job.good_job_concurrency_key ||= job._good_job_concurrency_key
|
|
37
|
+
key = job.good_job_concurrency_key
|
|
38
|
+
next(block.call) if key.blank?
|
|
39
|
+
|
|
33
40
|
enqueue_limit = job.class.good_job_concurrency_config[:enqueue_limit]
|
|
34
41
|
enqueue_limit = instance_exec(&enqueue_limit) if enqueue_limit.respond_to?(:call)
|
|
35
42
|
enqueue_limit = nil unless enqueue_limit.present? && (0...Float::INFINITY).cover?(enqueue_limit)
|
|
@@ -43,11 +50,6 @@ module GoodJob
|
|
|
43
50
|
limit = enqueue_limit || total_limit
|
|
44
51
|
next(block.call) unless limit
|
|
45
52
|
|
|
46
|
-
# Only generate the concurrency key on the initial enqueue in case it is dynamic
|
|
47
|
-
job.good_job_concurrency_key ||= job._good_job_concurrency_key
|
|
48
|
-
key = job.good_job_concurrency_key
|
|
49
|
-
next(block.call) if key.blank?
|
|
50
|
-
|
|
51
53
|
GoodJob::Execution.advisory_lock_key(key, function: "pg_advisory_lock") do
|
|
52
54
|
enqueue_concurrency = if enqueue_limit
|
|
53
55
|
GoodJob::Execution.where(concurrency_key: key).unfinished.advisory_unlocked.count
|
|
@@ -117,11 +119,10 @@ module GoodJob
|
|
|
117
119
|
key = self.class.good_job_concurrency_config[:key]
|
|
118
120
|
return if key.blank?
|
|
119
121
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
end
|
|
122
|
+
key = key.respond_to?(:call) ? instance_exec(&key) : key
|
|
123
|
+
raise TypeError, "Concurrency key must be a String; was a #{key.class}" unless VALID_TYPES.any? { |type| key.is_a?(type) }
|
|
124
|
+
|
|
125
|
+
key
|
|
125
126
|
end
|
|
126
127
|
end
|
|
127
128
|
end
|
|
@@ -10,6 +10,8 @@ module GoodJob
|
|
|
10
10
|
# The JobPerformer must be safe to execute across multiple threads.
|
|
11
11
|
#
|
|
12
12
|
class JobPerformer
|
|
13
|
+
cattr_accessor :performing_active_job_ids, default: Concurrent::Set.new
|
|
14
|
+
|
|
13
15
|
# @param queue_string [String] Queues to execute jobs from
|
|
14
16
|
def initialize(queue_string)
|
|
15
17
|
@queue_string = queue_string
|
|
@@ -24,7 +26,13 @@ module GoodJob
|
|
|
24
26
|
# Perform the next eligible job
|
|
25
27
|
# @return [Object, nil] Returns job result or +nil+ if no job was found
|
|
26
28
|
def next
|
|
27
|
-
|
|
29
|
+
active_job_id = nil
|
|
30
|
+
job_query.perform_with_advisory_lock(parsed_queues: parsed_queues, queue_select_limit: GoodJob.configuration.queue_select_limit) do |execution|
|
|
31
|
+
active_job_id = execution.active_job_id
|
|
32
|
+
performing_active_job_ids << active_job_id
|
|
33
|
+
end
|
|
34
|
+
ensure
|
|
35
|
+
performing_active_job_ids.delete(active_job_id)
|
|
28
36
|
end
|
|
29
37
|
|
|
30
38
|
# Tests whether this performer should be used in GoodJob's current state.
|
|
@@ -85,6 +85,19 @@ module GoodJob
|
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
def scheduler_shutdown_kill(event)
|
|
89
|
+
process_id = event.payload[:process_id]
|
|
90
|
+
|
|
91
|
+
warn(tags: [process_id]) do
|
|
92
|
+
active_job_ids = event.payload.fetch(:active_job_ids, [])
|
|
93
|
+
if active_job_ids.any?
|
|
94
|
+
"GoodJob scheduler has been killed. The following Active Jobs were interrupted: #{active_job_ids.join(' ')}"
|
|
95
|
+
else
|
|
96
|
+
"GoodJob scheduler has been killed."
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
88
101
|
# @!macro notification_responder
|
|
89
102
|
def scheduler_restart_pools(event)
|
|
90
103
|
process_id = event.payload[:process_id]
|
data/lib/good_job/scheduler.rb
CHANGED
|
@@ -121,7 +121,11 @@ module GoodJob # :nodoc:
|
|
|
121
121
|
|
|
122
122
|
if executor.shuttingdown? && timeout
|
|
123
123
|
executor_wait = timeout.negative? ? nil : timeout
|
|
124
|
-
|
|
124
|
+
|
|
125
|
+
unless executor.wait_for_termination(executor_wait)
|
|
126
|
+
instrument("scheduler_shutdown_kill", { active_job_ids: @performer.performing_active_job_ids.to_a })
|
|
127
|
+
executor.kill
|
|
128
|
+
end
|
|
125
129
|
end
|
|
126
130
|
end
|
|
127
131
|
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: 3.
|
|
4
|
+
version: 3.8.0
|
|
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-01-
|
|
11
|
+
date: 2023-01-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activejob
|
|
@@ -392,6 +392,7 @@ files:
|
|
|
392
392
|
- app/views/layouts/good_job/application.html.erb
|
|
393
393
|
- config/locales/en.yml
|
|
394
394
|
- config/locales/es.yml
|
|
395
|
+
- config/locales/fr.yml
|
|
395
396
|
- config/locales/nl.yml
|
|
396
397
|
- config/locales/ru.yml
|
|
397
398
|
- config/locales/ua.yml
|