good_job 4.1.1 → 4.2.0

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: 660e78528305c41b14c2926d9747037a091b57f952acd14246af99180991b434
4
- data.tar.gz: 8bc407843b2d17fbeceb36507eb2e06177460f1bc4b8b4133560e1c4daa6ce3e
3
+ metadata.gz: 6b8f73f25f420a1b95841f757ef3eae435fc19e442f157bae03af0e751d619a2
4
+ data.tar.gz: e6737d5a487ed8d43c0c9dc078b72c075784cfb00889835e63b8ca2ba8788333
5
5
  SHA512:
6
- metadata.gz: 8847a962731fec2c13683d3948e3ae51c0730bbcdd81853dfa3d6c2168bb05105ae2cf4c8f073a9c133d3f634473bdfaf58fefc08b07a0bbb8f51686e4b62ff0
7
- data.tar.gz: c89b843399fe9bdc0d492c89ce1f481da62201689cc0f15ada8d73135308be1ee23295e54bae1fa586d1c9a50e2ca62a072784a4ac0fb9a5be3ee83ed374b1d7
6
+ metadata.gz: fd113e9ed755d014fdbd324bd7aaf62837e384176412d7eeeb4bf277fbd7ed9cb5eba82a39dc4f1e54f4753e635f8c8076194f45d1de461f92301864081cf08f
7
+ data.tar.gz: 9e028ead209f0467bfe8e2d323ebfe812503ef8310a792270604b525f4aeb5429b7857fbf644bfbc600e14593c0545cf0e628f309aabb8276ca34c6f3ae98367
data/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## [v4.2.0](https://github.com/bensheldon/good_job/tree/v4.2.0) (2024-08-16)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.1.1...v4.2.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Add retry functionality for batches [\#1456](https://github.com/bensheldon/good_job/pull/1456) ([bensheldon](https://github.com/bensheldon))
10
+
11
+ **Fixed bugs:**
12
+
13
+ - respect perform\_throttle even if perform\_limit is provided [\#1470](https://github.com/bensheldon/good_job/pull/1470) ([doits](https://github.com/doits))
14
+ - Do not use advisory lock on heartbeat in production [\#1451](https://github.com/bensheldon/good_job/pull/1451) ([bensheldon](https://github.com/bensheldon))
15
+
16
+ **Closed issues:**
17
+
18
+ - `perform_limit` and `perform_throttle` don't work both [\#1469](https://github.com/bensheldon/good_job/issues/1469)
19
+ - Edge rails changes breaking binding commits [\#1466](https://github.com/bensheldon/good_job/issues/1466)
20
+ - Dynamic creation of CronEntries [\#1457](https://github.com/bensheldon/good_job/issues/1457)
21
+ - Batch callback job not enqueued after success of retried job [\#1450](https://github.com/bensheldon/good_job/issues/1450)
22
+
23
+ **Merged pull requests:**
24
+
25
+ - Update cron documentation to remove confusion about multiple processes [\#1467](https://github.com/bensheldon/good_job/pull/1467) ([bensheldon](https://github.com/bensheldon))
26
+ - Update compatibility matrix, remove compatibility code [\#1465](https://github.com/bensheldon/good_job/pull/1465) ([Earlopain](https://github.com/Earlopain))
27
+ - Run tests with warnings enabled [\#1462](https://github.com/bensheldon/good_job/pull/1462) ([Earlopain](https://github.com/Earlopain))
28
+ - Add appraisal for Rails 7.2; bracket lowest PG version instead of enumerating all [\#1460](https://github.com/bensheldon/good_job/pull/1460) ([bensheldon](https://github.com/bensheldon))
29
+ - Fix a few method redefinition warnings [\#1459](https://github.com/bensheldon/good_job/pull/1459) ([Earlopain](https://github.com/Earlopain))
30
+ - Bump rexml from 3.3.2 to 3.3.3 [\#1455](https://github.com/bensheldon/good_job/pull/1455) ([dependabot[bot]](https://github.com/apps/dependabot))
31
+ - Remove `smaller_number_is_higher_priority` option from v4 [\#1453](https://github.com/bensheldon/good_job/pull/1453) ([bensheldon](https://github.com/bensheldon))
32
+
3
33
  ## [v4.1.1](https://github.com/bensheldon/good_job/tree/v4.1.1) (2024-07-31)
4
34
 
5
35
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.99.2...v4.1.1)
data/README.md CHANGED
@@ -164,8 +164,8 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
164
164
 
165
165
  ## Compatibility
166
166
 
167
- - **Ruby on Rails:** 6.0+
168
- - **Ruby:** Ruby 2.6+. JRuby 9.3+
167
+ - **Ruby on Rails:** 6.1+
168
+ - **Ruby:** Ruby 3.0+. JRuby 9.4+
169
169
  - **Postgres:** 10.0+
170
170
 
171
171
  ## Configuration
@@ -307,7 +307,7 @@ Available configuration options are:
307
307
  - `inline_execution_respects_schedule` (boolean) Opt-in to future behavior of inline execution respecting scheduled jobs. Defaults to `false`.
308
308
  - `logger` ([Rails Logger](https://api.rubyonrails.org/classes/ActiveSupport/Logger.html)) lets you set a custom logger for GoodJob. It should be an instance of a Rails `Logger` (Default: `Rails.logger`).
309
309
  - `preserve_job_records` (boolean) keeps job records in your database even after jobs are completed. (Default: `true`)
310
- - `smaller_number_is_higher_priority` (boolean) allows you to specifiy that jobs should be run in ascending order of priority (smallest priority numbers first). This will be enabled by default in the next major version of GoodJob (v4.0), but jobs with the highest priority number are run first by default in all earlier versions of GoodJob.
310
+ - `advisory_lock_heartbeat` (boolean) whether to use an advisory lock for the purpose of determining whether an execeution process is active. (Default `true` in Development; `false` in other environments)
311
311
  - `retry_on_unhandled_error` (boolean) causes jobs to be re-queued and retried if they raise an instance of `StandardError`. Be advised this may lead to jobs being repeated infinitely ([see below for more on retries](#retries)). Instances of `Exception`, like SIGINT, will *always* be retried, regardless of this attribute’s value. (Default: `false`)
312
312
  - `on_thread_error` (proc, lambda, or callable) will be called when there is an Exception. It can be useful for logging errors to bug tracking services, like Sentry or Airbrake. Example:
313
313
 
@@ -499,7 +499,9 @@ As a second example, you may wish to show a link to a log aggregator next to eac
499
499
 
500
500
  ### Job priority
501
501
 
502
- Higher priority numbers run first in all versions of GoodJob v3.x and below. GoodJob v4.x will change job `priority` to give smaller numbers higher priority (default: `0`), in accordance with Active Job's definition of priority (see #524). To opt-in to this behavior now, set `config.good_job.smaller_number_is_higher_priority = true` in your GoodJob initializer or `application.rb`.
502
+ Smaller `priority` values have higher priority and run first (default: `0`), in accordance with [Active Job's definition of priority](https://github.com/rails/rails/blob/e17faead4f2aff28da079d50f02ea5b015322d5b/activejob/lib/active_job/core.rb#L22).
503
+
504
+ Prior to GoodJob v4, this was reversed: higher priority numbers ran first in all versions of GoodJob v3.x and below. When migrating from v3 to v4, new behavior can be opted into by setting `config.good_job.smaller_number_is_higher_priority = true` in your GoodJob initializer or `application.rb`.
503
505
 
504
506
  ### Labelled jobs
505
507
 
@@ -611,9 +613,7 @@ GoodJob's concurrency control strategy for `perform_limit` is "optimistic retry
611
613
 
612
614
  GoodJob can enqueue Active Job jobs on a recurring basis that can be used as a replacement for cron.
613
615
 
614
- Cron-style jobs can be performed by any GoodJob process (e.g., CLI or `:async` execution mode) that has `config.good_job.enable_cron` set to `true`. That is, one or more job executor processes can be configured to perform recurring jobs.
615
-
616
- GoodJob's cron uses unique indexes to ensure that only a single job is enqueued at the given time interval. In order for this to work, GoodJob must preserve cron-created job records; these records will be automatically deleted like any other preserved record.
616
+ Cron-style jobs can be enequeued by any GoodJob process (e.g., CLI or `:async` execution mode) that has `config.good_job.enable_cron` set to `true`. Enabling cron on multiple processes will not enqueue duplicate jobs; GoodJob's cron uses unique indexes to ensure that only a single job is enqueued for a given time interval. In order for this to work, GoodJob must preserve cron-created job records; these records will be automatically deleted like any other preserved record.
617
617
 
618
618
  Cron-format is parsed by the [`fugit`](https://github.com/floraison/fugit) gem, which has support for seconds-level resolution (e.g. `* * * * * *`) and natural language parsing (e.g. `every second`).
619
619
 
@@ -622,8 +622,8 @@ If you use the [Dashboard](#dashboard) the scheduled tasks can be viewed in the
622
622
  ```ruby
623
623
  # config/environments/application.rb or a specific environment e.g. production.rb
624
624
 
625
- # Enable cron in this process, e.g., only run on the first Heroku worker process
626
- config.good_job.enable_cron = ENV['DYNO'] == 'worker.1' # or `true` or via $GOOD_JOB_ENABLE_CRON
625
+ # Enable cron enqueuing in this process
626
+ config.good_job.enable_cron = true
627
627
 
628
628
  # Configure cron with a hash that has a unique key for each recurring job
629
629
  config.good_job.cron = {
@@ -890,7 +890,7 @@ To upgrade:
890
890
 
891
891
  Notable changes:
892
892
 
893
- - Only supports Rails 6.1+, CRuby 3.0+ and JRuby 9.4+, Postgres 12+. Rails 6.0 is no longer supported. CRuby 2.6 and 2.7 are no longer supported. JRuby 9.3 is no longer supported.
893
+ - Only supports Rails 6.1+, CRuby 3.0+ and JRuby 9.4+. Rails 6.0 is no longer supported. CRuby 2.6 and 2.7 are no longer supported. JRuby 9.3 is no longer supported.
894
894
  - Changes job `priority` to give smaller numbers higher priority (default: `0`), in accordance with Active Job's definition of priority.
895
895
  - Enqueues and executes jobs via the `GoodJob::Job` model instead of `GoodJob::Execution`
896
896
  - Setting `config.good_job.cleanup_interval_jobs`, `GOOD_JOB_CLEANUP_INTERVAL_JOBS`, `config.good_job.cleanup_interval_seconds`, or `GOOD_JOB_CLEANUP_INTERVAL_SECONDS` to `nil` or `""` no longer disables count- or time-based cleanups. Set to `false` to disable, or `-1` to run a cleanup after every job execution.
@@ -9,5 +9,11 @@ module GoodJob
9
9
  def show
10
10
  @batch = GoodJob::BatchRecord.find(params[:id])
11
11
  end
12
+
13
+ def retry
14
+ @batch = GoodJob::Batch.find(params[:id])
15
+ @batch.retry
16
+ redirect_back(fallback_location: batches_path, notice: t(".notice"))
17
+ end
12
18
  end
13
19
  end
@@ -15,9 +15,9 @@ module GoodJob
15
15
  discarded: 5,
16
16
  }
17
17
  if Gem::Version.new(Rails.version) >= Gem::Version.new('7.1.0.a')
18
- enum :error_event, error_event_enum, validate: { allow_nil: true }
18
+ enum :error_event, error_event_enum, validate: { allow_nil: true }, scopes: false
19
19
  else
20
- enum error_event: error_event_enum
20
+ enum error_event: error_event_enum, _scopes: false
21
21
  end
22
22
  end
23
23
  end
@@ -92,10 +92,12 @@ module GoodJob
92
92
  if record.new_record?
93
93
  record.save!
94
94
  else
95
- record.with_advisory_lock(function: "pg_advisory_lock") do
96
- record.enqueued_at_will_change!
97
- record.finished_at_will_change!
98
- record.update!(enqueued_at: nil, finished_at: nil)
95
+ record.transaction do
96
+ record.with_advisory_lock(function: "pg_advisory_xact_lock") do
97
+ record.enqueued_at_will_change!
98
+ record.finished_at_will_change!
99
+ record.update!(enqueued_at: nil, finished_at: nil)
100
+ end
99
101
  end
100
102
  end
101
103
 
@@ -135,6 +137,21 @@ module GoodJob
135
137
  buffer.active_jobs
136
138
  end
137
139
 
140
+ def retry
141
+ Rails.application.executor.wrap do
142
+ buffer = GoodJob::Adapter::InlineBuffer.capture do
143
+ record.transaction do
144
+ record.with_advisory_lock(function: "pg_advisory_xact_lock") do
145
+ record.update!(discarded_at: nil, finished_at: nil)
146
+ record.jobs.discarded.each(&:retry_job)
147
+ record._continue_discard_or_finish(lock: false)
148
+ end
149
+ end
150
+ end
151
+ buffer.call
152
+ end
153
+ end
154
+
138
155
  def active_jobs
139
156
  record.jobs.map(&:active_job)
140
157
  end
@@ -84,11 +84,7 @@ module GoodJob
84
84
  end
85
85
  end
86
86
 
87
- if Rails.gem_version < Gem::Version.new('6.1.0.alpha')
88
- # serialize does not yet take a default value, must set via Attributes API
89
- attribute :serialized_properties, :json, default: -> { {} }
90
- serialize :serialized_properties, PropertySerializer
91
- elsif Rails.gem_version < Gem::Version.new('7.1.0.alpha')
87
+ if Rails.gem_version < Gem::Version.new('7.1.0.alpha')
92
88
  serialize :serialized_properties, PropertySerializer, default: -> { {} }
93
89
  else
94
90
  serialize :serialized_properties, coder: PropertySerializer, default: -> { {} }
@@ -57,9 +57,9 @@ module GoodJob
57
57
  # Execution errored, will run in the future
58
58
  scope :retried, -> { where(finished_at: nil).where(coalesce_scheduled_at_created_at.gt(bind_value('coalesce', Time.current, ActiveRecord::Type::DateTime))).where(params_execution_count.gt(1)) }
59
59
  # Immediate/Scheduled time to run has passed, waiting for an available thread run
60
- scope :queued, -> { where(performed_at: nil, finished_at: nil).where(coalesce_scheduled_at_created_at.lteq(bind_value('coalesce', Time.current, ActiveRecord::Type::DateTime))).joins_advisory_locks.where(pg_locks: { locktype: nil }) }
60
+ scope :queued, -> { where(performed_at: nil, finished_at: nil).where(coalesce_scheduled_at_created_at.lteq(bind_value('coalesce', Time.current, ActiveRecord::Type::DateTime))) }
61
61
  # Advisory locked and executing
62
- scope :running, -> { where.not(performed_at: nil).where(finished_at: nil).joins_advisory_locks.where.not(pg_locks: { locktype: nil }) }
62
+ scope :running, -> { where.not(performed_at: nil).where(finished_at: nil) }
63
63
  # Finished executing (succeeded or discarded)
64
64
  scope :finished, -> { where.not(finished_at: nil) }
65
65
  # Completed executing successfully
@@ -99,13 +99,7 @@ module GoodJob
99
99
  # @!method priority_ordered
100
100
  # @!scope class
101
101
  # @return [ActiveRecord::Relation]
102
- scope :priority_ordered, (lambda do
103
- if GoodJob.configuration.smaller_number_is_higher_priority
104
- order('priority ASC NULLS LAST')
105
- else
106
- order('priority DESC NULLS LAST')
107
- end
108
- end)
102
+ scope :priority_ordered, -> { order('priority ASC NULLS LAST') }
109
103
 
110
104
  # Order jobs by created_at, for first-in first-out
111
105
  # @!method creation_ordered
@@ -146,24 +140,6 @@ module GoodJob
146
140
  # @return [ActiveRecord::Relation]
147
141
  scope :schedule_ordered, -> { order(coalesce_scheduled_at_created_at.asc) }
148
142
 
149
- # Get completed jobs before the given timestamp. If no timestamp is
150
- # provided, get *all* completed jobs. By default, GoodJob
151
- # destroys jobs after they're completed, meaning this returns no jobs.
152
- # However, if you have changed {GoodJob.preserve_job_records}, this may
153
- # find completed Jobs.
154
- # @!method finished(timestamp = nil)
155
- # @!scope class
156
- # @param timestamp (Float)
157
- # Get jobs that finished before this time (in epoch time).
158
- # @return [ActiveRecord::Relation]
159
- scope :finished, ->(timestamp = nil) { timestamp ? where(arel_table['finished_at'].lteq(bind_value('finished_at', timestamp, ActiveRecord::Type::DateTime))) : where.not(finished_at: nil) }
160
-
161
- # Get Jobs that started but not finished yet.
162
- # @!method running
163
- # @!scope class
164
- # @return [ActiveRecord::Relation]
165
- scope :running, -> { where.not(performed_at: nil).where(finished_at: nil) }
166
-
167
143
  # Get Jobs on queues that match the given queue string.
168
144
  # @!method queue_string(string)
169
145
  # @!scope class
@@ -20,9 +20,9 @@ module GoodJob # :nodoc:
20
20
  advisory: 0,
21
21
  }
22
22
  if Gem::Version.new(Rails.version) >= Gem::Version.new('7.1.0.a')
23
- enum :lock_type, lock_type_enum, validate: { allow_nil: true }
23
+ enum :lock_type, lock_type_enum, validate: { allow_nil: true }, scopes: false
24
24
  else
25
- enum lock_type: lock_type_enum
25
+ enum lock_type: lock_type_enum, _scopes: false
26
26
  end
27
27
 
28
28
  has_many :locked_jobs, class_name: "GoodJob::Job", foreign_key: :locked_by_id, inverse_of: :locked_by_process, dependent: nil
@@ -56,7 +56,7 @@ module GoodJob # :nodoc:
56
56
  end
57
57
  end
58
58
 
59
- def self.create_record(id:, with_advisory_lock: false)
59
+ def self.find_or_create_record(id:, with_advisory_lock: false)
60
60
  attributes = {
61
61
  id: id,
62
62
  state: process_state,
@@ -66,6 +66,17 @@ module GoodJob # :nodoc:
66
66
  attributes[:lock_type] = :advisory
67
67
  end
68
68
  create!(attributes)
69
+ rescue ActiveRecord::RecordNotUnique
70
+ find_by(id: id).tap do |existing_record|
71
+ next unless existing_record
72
+
73
+ if with_advisory_lock
74
+ existing_record.advisory_lock!
75
+ existing_record.update(lock_type: :advisory, state: process_state, updated_at: Time.current)
76
+ else
77
+ existing_record.update(lock_type: nil, state: process_state, updated_at: Time.current)
78
+ end
79
+ end
69
80
  end
70
81
 
71
82
  def self.process_state
@@ -59,6 +59,12 @@
59
59
  <%= batch.jobs.size %>
60
60
  </div>
61
61
  <div class="col text-end">
62
+ <% if batch.discarded? %>
63
+ <%= link_to retry_batch_path(batch), method: :put, class: "btn btn-sm btn-outline-primary", title: t("good_job.batches.actions.retry"), data: { confirm: t("good_job.batches.actions.confirm_retry") } do %>
64
+ <%= render_icon "arrow_clockwise" %>
65
+ <%= t "good_job.batches.actions.retry" %>
66
+ <% end %>
67
+ <% end %>
62
68
  <%= tag.button type: "button", class: "btn btn-sm text-muted", role: "button",
63
69
  title: t("good_job.actions.inspect"),
64
70
  data: { bs_toggle: "collapse", bs_target: "##{dom_id(batch, 'properties')}" },
@@ -10,6 +10,14 @@
10
10
  <h2 class="h5 mt-2"><%= @batch.description %></h2>
11
11
  </nav>
12
12
  </div>
13
+ <div class="col text-end">
14
+ <% if @batch.discarded? %>
15
+ <%= button_to retry_batch_path(@batch), method: :put, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: t("good_job.batches.actions.retry") }, title: t("good_job.batches.actions.retry"), data: { confirm: t("good_job.batches.actions.confirm_retry") } do %>
16
+ <%= render_icon "arrow_clockwise" %>
17
+ <%= t "good_job.actions.retry" %>
18
+ <% end %>
19
+ <% end %>
20
+ </div>
13
21
  </div>
14
22
  </div>
15
23
  </div>
@@ -9,6 +9,9 @@ de:
9
9
  reschedule: Umplanen
10
10
  retry: Wiederholen
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Bist du sicher, dass du diesen Batch wiederholen willst?
14
+ retry: Batch wiederholen
12
15
  index:
13
16
  older_batches: Ältere Batches
14
17
  title: Batches
@@ -24,6 +27,8 @@ de:
24
27
  retry: Job wiederholen
25
28
  title: Aktionen
26
29
  no_jobs_found: Keine Jobs gefunden.
30
+ retry:
31
+ notice: Batch wurde wiederholt
27
32
  show:
28
33
  attributes: Attribute
29
34
  batched_jobs: Batch-Jobs
@@ -9,6 +9,9 @@ en:
9
9
  reschedule: Reschedule
10
10
  retry: Retry
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Are you sure you want to retry this batch?
14
+ retry: Retry
12
15
  index:
13
16
  older_batches: Older batches
14
17
  title: Batches
@@ -24,6 +27,8 @@ en:
24
27
  retry: Retry Job
25
28
  title: Actions
26
29
  no_jobs_found: No jobs found.
30
+ retry:
31
+ notice: Batch has been retried
27
32
  show:
28
33
  attributes: Attributes
29
34
  batched_jobs: Batched Jobs
@@ -9,6 +9,9 @@ es:
9
9
  reschedule: Reprogramar
10
10
  retry: Reintentar
11
11
  batches:
12
+ actions:
13
+ confirm_retry: "¿Estás seguro que querés reintentar este lote?"
14
+ retry: Reintentar
12
15
  index:
13
16
  older_batches: Lotes anteriores
14
17
  title: Lotes
@@ -24,6 +27,8 @@ es:
24
27
  retry: Reintentar tarea
25
28
  title: Acciones
26
29
  no_jobs_found: No hay tareas.
30
+ retry:
31
+ notice: El lote ha sido reintentado
27
32
  show:
28
33
  attributes: Atributos
29
34
  batched_jobs: Tareas en lote
@@ -9,6 +9,9 @@ fr:
9
9
  reschedule: Reprogrammer
10
10
  retry: Recommencez
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Voulez-vous vraiment réessayer ce lot ?
14
+ retry: Réessayer
12
15
  index:
13
16
  older_batches: Lots plus anciens
14
17
  title: Lots
@@ -24,6 +27,8 @@ fr:
24
27
  retry: Réessayer le job
25
28
  title: Actions
26
29
  no_jobs_found: Aucun job trouvé.
30
+ retry:
31
+ notice: Le lot a été réessayé
27
32
  show:
28
33
  attributes: Attributs
29
34
  batched_jobs: Jobs groupés
@@ -9,6 +9,9 @@ it:
9
9
  reschedule: Riprogramma
10
10
  retry: Riprova
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Sei sicuro di voler riprovare questo batch?
14
+ retry: Riprova
12
15
  index:
13
16
  older_batches: Batch più vecchi
14
17
  title: Batch
@@ -24,6 +27,8 @@ it:
24
27
  retry: Riprova job
25
28
  title: Azioni
26
29
  no_jobs_found: Nessun job trovato.
30
+ retry:
31
+ notice: Il batch è stato riprovato
27
32
  show:
28
33
  attributes: Attributi
29
34
  batched_jobs: Job raggruppati
@@ -9,6 +9,9 @@ ja:
9
9
  reschedule: 再スケジュールする
10
10
  retry: 再試行する
11
11
  batches:
12
+ actions:
13
+ confirm_retry: このバッチを再試行してもよろしいですか?
14
+ retry: バッチを再試行する
12
15
  index:
13
16
  older_batches: より古いバッチ
14
17
  title: バッチ
@@ -24,6 +27,8 @@ ja:
24
27
  retry: ジョブを再試行する
25
28
  title: アクション
26
29
  no_jobs_found: ジョブが見つかりませんでした。
30
+ retry:
31
+ notice: バッチが再試行されました
27
32
  show:
28
33
  attributes: 属性
29
34
  batched_jobs: バッチ処理されたジョブ
@@ -122,9 +127,9 @@ ja:
122
127
  discard:
123
128
  notice: ジョブが破棄されました
124
129
  executions:
125
- application_trace: Application Trace
126
- full_trace: Full Trace
127
- in_queue: 待機中
130
+ application_trace: アプリケーショントレース
131
+ full_trace: フルトレース
132
+ in_queue: キュー内
128
133
  runtime: 実行時間
129
134
  title: 実行
130
135
  force_discard:
@@ -198,8 +203,8 @@ ja:
198
203
  index:
199
204
  average_duration: 平均所要時間
200
205
  chart_title: ジョブの総実行時間(秒
201
- executions: 処刑
202
- job_class: 職種
206
+ executions: 実行
207
+ job_class: ジョブクラス
203
208
  maximum_duration: 最大持続時間
204
209
  minimum_duration: 最小期間
205
210
  title: パフォーマンス
@@ -9,6 +9,9 @@ ko:
9
9
  reschedule: 재예약하기
10
10
  retry: 다시 시도하기
11
11
  batches:
12
+ actions:
13
+ confirm_retry: 이 배치를 다시 시도하시겠습니까?
14
+ retry: 배치 다시 시도
12
15
  index:
13
16
  older_batches: 더 오래된 배치
14
17
  title: 배치
@@ -24,6 +27,8 @@ ko:
24
27
  retry: 작업 다시 시도
25
28
  title: 작업 액션
26
29
  no_jobs_found: 작업이 없습니다.
30
+ retry:
31
+ notice: 배치가 다시 시도되었습니다.
27
32
  show:
28
33
  attributes: 속성
29
34
  batched_jobs: 배치된 작업
@@ -122,8 +127,8 @@ ko:
122
127
  discard:
123
128
  notice: 작업이 폐기되었습니다.
124
129
  executions:
125
- application_trace: Application Trace
126
- full_trace: Full Trace
130
+ application_trace: 애플리케이션 추적
131
+ full_trace: 전체 추적
127
132
  in_queue: 대기 중
128
133
  runtime: 실행 시간
129
134
  title: 실행
@@ -198,8 +203,8 @@ ko:
198
203
  index:
199
204
  average_duration: 평균 지속 시간
200
205
  chart_title: 총 작업 실행 시간(초)
201
- executions: 처형
202
- job_class: 직업군
206
+ executions: 실행
207
+ job_class: 작업 클래스
203
208
  maximum_duration: 최대 기간
204
209
  minimum_duration: 최소 기간
205
210
  title: 성능
@@ -9,6 +9,9 @@ nl:
9
9
  reschedule: Opnieuw plannen
10
10
  retry: Opnieuw proberen
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Weet je zeker dat je deze batch opnieuw wilt proberen?
14
+ retry: Batch opnieuw proberen
12
15
  index:
13
16
  older_batches: Oudere partijen
14
17
  title: Partijen
@@ -24,6 +27,8 @@ nl:
24
27
  retry: Taak opnieuw
25
28
  title: Acties
26
29
  no_jobs_found: Geen vacatures gevonden.
30
+ retry:
31
+ notice: Batch is opnieuw geprobeerd
27
32
  show:
28
33
  attributes: attributen
29
34
  batched_jobs: Gegroepeerde banen
@@ -9,6 +9,9 @@ pt-BR:
9
9
  reschedule: Reagendar
10
10
  retry: Tentar novamente
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Tem certeza de que deseja tentar novamente este lote?
14
+ retry: Tentar novamente
12
15
  index:
13
16
  older_batches: Lotes antigos
14
17
  title: Lotes
@@ -24,6 +27,8 @@ pt-BR:
24
27
  retry: Tentar Tarefa Novamente
25
28
  title: Ações
26
29
  no_jobs_found: Nenhuma tarefa encontrada.
30
+ retry:
31
+ notice: O lote foi tentado novamente
27
32
  show:
28
33
  attributes: Atributos
29
34
  batched_jobs: Tarefas em Lote
@@ -9,6 +9,9 @@ ru:
9
9
  reschedule: Перенести
10
10
  retry: Повторить попытку
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Вы уверены, что хотите повторить эту группу заданий?
14
+ retry: Повторить группу заданий
12
15
  index:
13
16
  older_batches: Старые группы заданий
14
17
  title: Группы заданий
@@ -24,6 +27,8 @@ ru:
24
27
  retry: Повторить задание
25
28
  title: Действия
26
29
  no_jobs_found: Заданий не найдено
30
+ retry:
31
+ notice: Группа заданий была повторена
27
32
  show:
28
33
  attributes: Атрибуты
29
34
  batched_jobs: Группы заданий
@@ -9,6 +9,9 @@ tr:
9
9
  reschedule: Yeniden planla
10
10
  retry: Tekrar dene
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Bu grubu yeniden denemek istediğinizden emin misiniz?
14
+ retry: Grubu yeniden dene
12
15
  index:
13
16
  older_batches: Daha eski toplu işlemler
14
17
  title: Toplu İşlemler
@@ -24,6 +27,8 @@ tr:
24
27
  retry: İşi Tekrar Dene
25
28
  title: İşlemler
26
29
  no_jobs_found: İş bulunamadı.
30
+ retry:
31
+ notice: Grup yeniden denendi
27
32
  show:
28
33
  attributes: Özellikler
29
34
  batched_jobs: Toplu İşlenmiş İşler
@@ -9,6 +9,9 @@ uk:
9
9
  reschedule: Перепланувати
10
10
  retry: Повторити
11
11
  batches:
12
+ actions:
13
+ confirm_retry: Ви впевнені, що хочете повторити цю групу завдань?
14
+ retry: Повторити групу завдань
12
15
  index:
13
16
  older_batches: Старі пакети
14
17
  title: Пакети
@@ -24,6 +27,8 @@ uk:
24
27
  retry: Повторити задачу
25
28
  title: Дії
26
29
  no_jobs_found: Задачі не знайдені.
30
+ retry:
31
+ notice: Групу завдань було повторено
27
32
  show:
28
33
  attributes: Атрибути
29
34
  batched_jobs: Задачі в пакеті
@@ -256,7 +261,7 @@ uk:
256
261
  queue_name: Назва черги
257
262
  search: Пошук
258
263
  navbar:
259
- batches: Batches
264
+ batches: Пакети
260
265
  cron_schedules: Cron
261
266
  jobs: Задачі
262
267
  live_poll: Живе Опитування
data/config/routes.rb CHANGED
@@ -19,7 +19,11 @@ GoodJob::Engine.routes.draw do
19
19
  get 'jobs/metrics/primary_nav', to: 'metrics#primary_nav', as: :metrics_primary_nav
20
20
  get 'jobs/metrics/job_status', to: 'metrics#job_status', as: :metrics_job_status
21
21
 
22
- resources :batches, only: %i[index show]
22
+ resources :batches, only: %i[index show] do
23
+ member do
24
+ put :retry
25
+ end
26
+ end
23
27
 
24
28
  resources :cron_entries, only: %i[index show], param: :cron_key do
25
29
  member do
@@ -35,6 +39,6 @@ GoodJob::Engine.routes.draw do
35
39
 
36
40
  scope :frontend, controller: :frontends, defaults: { version: GoodJob::VERSION.tr(".", "-") } do
37
41
  get "modules/:version/:id", action: :module, as: :frontend_module, constraints: { format: 'js' }
38
- get "static/:version/:id", action: :static, as: :frontend_static, constraints: { format: %w[css js svg] }
42
+ get "static/:version/:id", action: :static, as: :frontend_static
39
43
  end
40
44
  end
@@ -149,8 +149,10 @@ module GoodJob
149
149
  .order(Arel.sql("COALESCE(performed_at, scheduled_at, created_at) ASC"))
150
150
  .limit(limit).pluck(:active_job_id)
151
151
  # The current job has already been locked and will appear in the previous query
152
- exceeded = :limit unless allowed_active_job_ids.include?(job.job_id)
153
- next
152
+ unless allowed_active_job_ids.include?(job.job_id)
153
+ exceeded = :limit
154
+ next
155
+ end
154
156
  end
155
157
 
156
158
  if throttle
@@ -165,8 +167,10 @@ module GoodJob
165
167
  .limit(throttle_limit)
166
168
  .pluck(:active_job_id)
167
169
 
168
- exceeded = :throttle unless allowed_active_job_ids.include?(job.job_id)
169
- next
170
+ unless allowed_active_job_ids.include?(job.job_id)
171
+ exceeded = :throttle
172
+ next
173
+ end
170
174
  end
171
175
  end
172
176
 
@@ -57,7 +57,7 @@ module GoodJob # :nodoc:
57
57
  if @record
58
58
  @record.refresh_if_stale
59
59
  else
60
- @record = GoodJob::Process.create_record(id: @record_id)
60
+ @record = GoodJob::Process.find_or_create_record(id: @record_id)
61
61
  create_refresh_task
62
62
  end
63
63
  value = @record&.id
@@ -89,7 +89,7 @@ module GoodJob # :nodoc:
89
89
  @advisory_locked_connection = WeakRef.new(@record.class.connection)
90
90
  end
91
91
  else
92
- @record = GoodJob::Process.create_record(id: @record_id, with_advisory_lock: true)
92
+ @record = GoodJob::Process.find_or_create_record(id: @record_id, with_advisory_lock: true)
93
93
  @advisory_locked_connection = WeakRef.new(@record.class.connection)
94
94
  create_refresh_task
95
95
  end
@@ -35,8 +35,6 @@ module GoodJob
35
35
  DEFAULT_DASHBOARD_LIVE_POLL_ENABLED = true
36
36
  # Default enqueue_after_transaction_commit
37
37
  DEFAULT_ENQUEUE_AFTER_TRANSACTION_COMMIT = false
38
- # Default smaller_number_is_higher_priority
39
- DEFAULT_SMALLER_NUMBER_IS_HIGHER_PRIORITY = true
40
38
 
41
39
  def self.validate_execution_mode(execution_mode)
42
40
  raise ArgumentError, "GoodJob execution mode must be one of #{EXECUTION_MODES.join(', ')}. It was '#{execution_mode}' which is not valid." unless execution_mode.in?(EXECUTION_MODES)
@@ -347,12 +345,6 @@ module GoodJob
347
345
  DEFAULT_ENABLE_LISTEN_NOTIFY
348
346
  end
349
347
 
350
- def smaller_number_is_higher_priority
351
- return rails_config[:smaller_number_is_higher_priority] unless rails_config[:smaller_number_is_higher_priority].nil?
352
-
353
- DEFAULT_SMALLER_NUMBER_IS_HIGHER_PRIORITY
354
- end
355
-
356
348
  def dashboard_default_locale
357
349
  rails_config[:dashboard_default_locale] || DEFAULT_DASHBOARD_DEFAULT_LOCALE
358
350
  end
@@ -385,6 +377,16 @@ module GoodJob
385
377
  end || false
386
378
  end
387
379
 
380
+ # Whether to take an advisory lock on the process record in the notifier reactor.
381
+ # @return [Boolean]
382
+ def advisory_lock_heartbeat
383
+ return options[:advisory_lock_heartbeat] unless options[:advisory_lock_heartbeat].nil?
384
+ return rails_config[:advisory_lock_heartbeat] unless rails_config[:advisory_lock_heartbeat].nil?
385
+ return ActiveModel::Type::Boolean.new.cast(env['GOOD_JOB_ADVISORY_LOCK_HEARTBEAT']) unless env['GOOD_JOB_ADVISORY_LOCK_HEARTBEAT'].nil?
386
+
387
+ Rails.env.development?
388
+ end
389
+
388
390
  private
389
391
 
390
392
  def rails_config
@@ -14,9 +14,10 @@ module GoodJob # :nodoc:
14
14
 
15
15
  # Registers the current process.
16
16
  def register_process
17
+ @advisory_lock_heartbeat = GoodJob.configuration.advisory_lock_heartbeat
17
18
  GoodJob::Process.override_connection(connection) do
18
19
  GoodJob::Process.cleanup
19
- @capsule.tracker.register(with_advisory_lock: true)
20
+ @capsule.tracker.register(with_advisory_lock: @advisory_lock_heartbeat)
20
21
  end
21
22
  end
22
23
 
@@ -33,7 +34,7 @@ module GoodJob # :nodoc:
33
34
  # Deregisters the current process.
34
35
  def deregister_process
35
36
  GoodJob::Process.override_connection(connection) do
36
- @capsule.tracker.unregister(with_advisory_lock: true)
37
+ @capsule.tracker.unregister(with_advisory_lock: @advisory_lock_heartbeat)
37
38
  end
38
39
  end
39
40
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GoodJob
4
4
  # GoodJob gem version.
5
- VERSION = '4.1.1'
5
+ VERSION = '4.2.0'
6
6
 
7
7
  # GoodJob version as Gem::Version object
8
8
  GEM_VERSION = Gem::Version.new(VERSION)
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.1.1
4
+ version: 4.2.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: 2024-07-31 00:00:00.000000000 Z
11
+ date: 2024-08-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob