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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fda5fd7d15b1e93616e9dfa44dad4ed89abbad549c5c83d85d3d0fadcb5a3082
4
- data.tar.gz: f114b7657cdd5d1845e9314688c0befaa3c1615df6b203fc6d9cd44e894e7071
3
+ metadata.gz: d5d0c455a8d5d8f18fda38f1f9f126cc406250d188ee313d0352717c829cd126
4
+ data.tar.gz: 208b61ec3b48a7973b160093100b216eafbb96eee604e5e7edc2e7fb67bedfba
5
5
  SHA512:
6
- metadata.gz: d1b5bbbc7f8e407a74d65976996f29df1bea1271a327733a5c685804984c7d5e95d696e3ec823995e856e17e7c22f24edbf7c8425d7caf7ec4795f94f5038357
7
- data.tar.gz: fad2cc50096beae6594326189defab7eec6527e2b2e297518e5c42f220eea3a6201ce7375864b95085ed0462d019da6829e8d34ee02e6ac042968a8f0096a059
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
- **Merged pull requests:**
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" # rubocop:disable Rails/I18nLocaleTexts
83
+ redirect_to jobs_path, notice: "Job has been destroyed"
84
84
  end
85
85
 
86
86
  private
@@ -212,6 +212,7 @@ module GoodJob
212
212
  break if execution.blank?
213
213
  break :unlocked unless execution&.executable?
214
214
 
215
+ yield(execution) if block_given?
215
216
  result = execution.perform
216
217
  end
217
218
  execution&.run_callbacks(:perform_unlocked)
@@ -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
- if key.respond_to? :call
121
- instance_exec(&key)
122
- else
123
- key
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
- job_query.perform_with_advisory_lock(parsed_queues: parsed_queues, queue_select_limit: GoodJob.configuration.queue_select_limit)
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]
@@ -121,7 +121,11 @@ module GoodJob # :nodoc:
121
121
 
122
122
  if executor.shuttingdown? && timeout
123
123
  executor_wait = timeout.negative? ? nil : timeout
124
- executor.kill unless executor.wait_for_termination(executor_wait)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '3.7.4'
4
+ VERSION = '3.8.0'
5
5
  end
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.7.4
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-10 00:00:00.000000000 Z
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