good_job 3.99.1 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -61
  3. data/app/charts/good_job/scheduled_by_queue_chart.rb +2 -2
  4. data/app/controllers/good_job/cron_entries_controller.rb +0 -8
  5. data/app/controllers/good_job/metrics_controller.rb +1 -1
  6. data/app/controllers/good_job/performances_controller.rb +5 -9
  7. data/app/models/concerns/good_job/filterable.rb +1 -1
  8. data/app/models/good_job/base_execution.rb +104 -201
  9. data/app/models/good_job/cron_entry.rb +0 -2
  10. data/app/models/good_job/discrete_execution.rb +1 -31
  11. data/app/models/good_job/execution.rb +3 -7
  12. data/app/models/good_job/job.rb +37 -116
  13. data/app/models/good_job/process.rb +7 -20
  14. data/app/views/good_job/batches/index.html.erb +11 -15
  15. data/app/views/good_job/jobs/_executions.erb +1 -1
  16. data/app/views/good_job/jobs/_table.erb +1 -1
  17. data/app/views/good_job/jobs/show.html.erb +1 -8
  18. data/app/views/good_job/performances/show.html.erb +33 -40
  19. data/config/locales/de.yml +1 -4
  20. data/config/locales/en.yml +1 -4
  21. data/config/locales/es.yml +1 -4
  22. data/config/locales/fr.yml +1 -4
  23. data/config/locales/it.yml +1 -4
  24. data/config/locales/ja.yml +1 -4
  25. data/config/locales/ko.yml +1 -4
  26. data/config/locales/nl.yml +1 -4
  27. data/config/locales/pt-BR.yml +1 -4
  28. data/config/locales/ru.yml +1 -4
  29. data/config/locales/tr.yml +1 -4
  30. data/config/locales/uk.yml +1 -4
  31. data/lib/generators/good_job/templates/update/migrations/01_create_good_jobs.rb.erb +65 -3
  32. data/lib/good_job/active_job_extensions/batches.rb +1 -1
  33. data/lib/good_job/active_job_extensions/concurrency.rb +10 -10
  34. data/lib/good_job/adapter.rb +13 -24
  35. data/lib/good_job/current_thread.rb +6 -6
  36. data/lib/good_job/job_performer.rb +2 -2
  37. data/lib/good_job/log_subscriber.rb +2 -10
  38. data/lib/good_job/notifier.rb +3 -3
  39. data/lib/good_job/version.rb +1 -1
  40. data/lib/good_job.rb +17 -22
  41. metadata +16 -30
  42. data/lib/generators/good_job/templates/update/migrations/02_create_good_job_settings.rb.erb +0 -20
  43. data/lib/generators/good_job/templates/update/migrations/03_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb.erb +0 -19
  44. data/lib/generators/good_job/templates/update/migrations/04_create_good_job_batches.rb.erb +0 -35
  45. data/lib/generators/good_job/templates/update/migrations/05_create_good_job_executions.rb.erb +0 -33
  46. data/lib/generators/good_job/templates/update/migrations/06_create_good_jobs_error_event.rb.erb +0 -16
  47. data/lib/generators/good_job/templates/update/migrations/07_recreate_good_job_cron_indexes_with_conditional.rb.erb +0 -45
  48. data/lib/generators/good_job/templates/update/migrations/08_create_good_job_labels.rb.erb +0 -15
  49. data/lib/generators/good_job/templates/update/migrations/09_create_good_job_labels_index.rb.erb +0 -22
  50. data/lib/generators/good_job/templates/update/migrations/10_remove_good_job_active_id_index.rb.erb +0 -21
  51. data/lib/generators/good_job/templates/update/migrations/11_create_index_good_job_jobs_for_candidate_lookup.rb.erb +0 -19
  52. data/lib/generators/good_job/templates/update/migrations/12_create_good_job_execution_error_backtrace.rb.erb +0 -15
  53. data/lib/generators/good_job/templates/update/migrations/13_create_good_job_process_lock_ids.rb.erb +0 -18
  54. data/lib/generators/good_job/templates/update/migrations/14_create_good_job_process_lock_indexes.rb.erb +0 -38
  55. data/lib/generators/good_job/templates/update/migrations/15_create_good_job_execution_duration.rb.erb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7dd2e7c483f6ded0e42c21101bd4e7e0ff7e3ac75cdc47855f215b1484ead2bd
4
- data.tar.gz: c74390ec62b82ba8b2281b6b14ea241726e75ad9bc1669ddf06f35511acda998
3
+ metadata.gz: 3a4006c920a731f763e36a964e7eb161a292e8a4b34bffa4b60b95b75145c28c
4
+ data.tar.gz: f54b107db6ac1e2304a4ee9e2d34fa65032dc2b1ab0425e0be5ea42d39e5590b
5
5
  SHA512:
6
- metadata.gz: 7de33180257e794e418416b7f83ab00fa64121e64a69a6be46e7c86301cbf750b4ae5ee7851aad02501d48ca64baf38d94782ab89852ae4a79e55870c76df5e3
7
- data.tar.gz: 36bc0111ecba9df0e983e44c2c418325b745fcc90fa8295d71da44ff4d63ad6fed733760e6355aa3f18a663d3d0d4d9df75cfac23f97cc2a2964b29fe4d5d99c
6
+ metadata.gz: 4474aaa0540dc5ff1bba65e8807a6fa69a9901f2e68051c57cf954e30270e9e6d7eaf52a3ce8ec7de6f48b16fc60fa05e796f595f14dfda41a76cbeb5b042543
7
+ data.tar.gz: cf8103c84fceffe91e4f7b0f5083c3989d2312a17ce96b1db01d7726a99b651c7d850f83fe23075c5a01628a825ef71d335d0eb42e91a478a62dd7772ee95e54
data/CHANGELOG.md CHANGED
@@ -1,66 +1,5 @@
1
1
  # Changelog
2
2
 
3
- ## [v3.99.1](https://github.com/bensheldon/good_job/tree/v3.99.1) (2024-07-10)
4
-
5
- [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.0.3...v3.99.1)
6
-
7
- **Merged pull requests:**
8
-
9
- - Add a little more wording to the v4 "ready to upgrade" instructions [\#1415](https://github.com/bensheldon/good_job/pull/1415) ([bensheldon](https://github.com/bensheldon))
10
-
11
- ## [v4.0.3](https://github.com/bensheldon/good_job/tree/v4.0.3) (2024-07-10)
12
-
13
- [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.0.2...v4.0.3)
14
-
15
- **Fixed bugs:**
16
-
17
- - Only set duration attribute to interval on Rails 6.1 [\#1412](https://github.com/bensheldon/good_job/pull/1412) ([bdewater-thatch](https://github.com/bdewater-thatch))
18
-
19
- **Closed issues:**
20
-
21
- - GoodJob error: TypeError: can't cast ActiveSupport::Duration \(on v4.0.0\) [\#1413](https://github.com/bensheldon/good_job/issues/1413)
22
- - Question: is it possible to clean a set of scheduled jobs \(by class name\) from console? [\#1410](https://github.com/bensheldon/good_job/issues/1410)
23
- - "Couldn't find GoodJob::BatchRecord" error [\#1387](https://github.com/bensheldon/good_job/issues/1387)
24
- - Empty alerts "\[\]"? [\#1372](https://github.com/bensheldon/good_job/issues/1372)
25
- - Release GoodJob 4.0 [\#764](https://github.com/bensheldon/good_job/issues/764)
26
-
27
- **Merged pull requests:**
28
-
29
- - Add Active Support load hooks for Job and \(Discrete\)Execution; move all outside class definition bodies [\#1414](https://github.com/bensheldon/good_job/pull/1414) ([bensheldon](https://github.com/bensheldon))
30
-
31
- ## [v4.0.2](https://github.com/bensheldon/good_job/tree/v4.0.2) (2024-07-08)
32
-
33
- [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.0.1...v4.0.2)
34
-
35
- **Fixed bugs:**
36
-
37
- - Fix a rails 6.1 deprecation warning for the duration attribute [\#1408](https://github.com/bensheldon/good_job/pull/1408) ([Earlopain](https://github.com/Earlopain))
38
- - Actually remove deprecated configuration for `cleanup_interval_seconds`, `cleanup_interval_jobs`; remove deprecated `Lockable` [\#1406](https://github.com/bensheldon/good_job/pull/1406) ([bensheldon](https://github.com/bensheldon))
39
-
40
- **Closed issues:**
41
-
42
- - PG::UndefinedColumn: ERROR: column good\_job\_processes.lock\_type does not exist [\#1405](https://github.com/bensheldon/good_job/issues/1405)
43
- - undefined method `duration=' for an instance of GoodJob::Execution [\#1404](https://github.com/bensheldon/good_job/issues/1404)
44
- - v3 deprecations are still present [\#1399](https://github.com/bensheldon/good_job/issues/1399)
45
-
46
- **Merged pull requests:**
47
-
48
- - Fix Batch integration test to not exhaust database connection thread pool [\#1409](https://github.com/bensheldon/good_job/pull/1409) ([bensheldon](https://github.com/bensheldon))
49
- - Discrete cleanup [\#1401](https://github.com/bensheldon/good_job/pull/1401) ([Earlopain](https://github.com/Earlopain))
50
-
51
- ## [v4.0.1](https://github.com/bensheldon/good_job/tree/v4.0.1) (2024-07-08)
52
-
53
- [Full Changelog](https://github.com/bensheldon/good_job/compare/v4.0.0...v4.0.1)
54
-
55
- **Fixed bugs:**
56
-
57
- - Actually change `smaller_number_is_higher_priority` for v4 [\#1402](https://github.com/bensheldon/good_job/pull/1402) ([Earlopain](https://github.com/Earlopain))
58
-
59
- **Merged pull requests:**
60
-
61
- - Bump prism/rbi dev dependency [\#1403](https://github.com/bensheldon/good_job/pull/1403) ([Earlopain](https://github.com/Earlopain))
62
- - Use index action for the performance controller [\#1398](https://github.com/bensheldon/good_job/pull/1398) ([Earlopain](https://github.com/Earlopain))
63
-
64
3
  ## [v4.0.0](https://github.com/bensheldon/good_job/tree/v4.0.0) (2024-07-07)
65
4
 
66
5
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.99.0...v4.0.0)
@@ -11,7 +11,7 @@ module GoodJob
11
11
  start_time = end_time - 1.day
12
12
  table_name = GoodJob::Job.table_name
13
13
 
14
- count_query = Arel.sql(GoodJob::Execution.pg_or_jdbc_query(<<~SQL.squish))
14
+ count_query = Arel.sql(GoodJob::Job.pg_or_jdbc_query(<<~SQL.squish))
15
15
  SELECT *
16
16
  FROM generate_series(
17
17
  date_trunc('hour', $1::timestamp),
@@ -35,7 +35,7 @@ module GoodJob
35
35
  ActiveRecord::Relation::QueryAttribute.new('start_time', start_time, ActiveRecord::Type::DateTime.new),
36
36
  ActiveRecord::Relation::QueryAttribute.new('end_time', end_time, ActiveRecord::Type::DateTime.new),
37
37
  ]
38
- executions_data = GoodJob::Execution.connection.exec_query(GoodJob::Execution.pg_or_jdbc_query(count_query), "GoodJob Dashboard Chart", binds)
38
+ executions_data = GoodJob::Job.connection.exec_query(GoodJob::Job.pg_or_jdbc_query(count_query), "GoodJob Dashboard Chart", binds)
39
39
 
40
40
  queue_names = executions_data.reject { |d| d['count'].nil? }.map { |d| d['queue_name'] || BaseFilter::EMPTY }.uniq
41
41
  labels = []
@@ -2,8 +2,6 @@
2
2
 
3
3
  module GoodJob
4
4
  class CronEntriesController < GoodJob::ApplicationController
5
- before_action :check_settings_migration!, only: [:enable, :disable]
6
-
7
5
  def index
8
6
  @cron_entries = CronEntry.all
9
7
  end
@@ -30,11 +28,5 @@ module GoodJob
30
28
  @cron_entry.disable
31
29
  redirect_back(fallback_location: cron_entries_path, notice: t(".notice"))
32
30
  end
33
-
34
- private
35
-
36
- def check_settings_migration!
37
- redirect_back(fallback_location: cron_entries_path, alert: t("good_job.cron_entries.pending_migrations")) unless GoodJob::Setting.migrated?
38
- end
39
31
  end
40
32
  end
@@ -4,7 +4,7 @@ module GoodJob
4
4
  class MetricsController < ApplicationController
5
5
  def primary_nav
6
6
  jobs_count = GoodJob::Job.count
7
- batches_count = GoodJob::BatchRecord.migrated? ? GoodJob::BatchRecord.all.size : 0
7
+ batches_count = GoodJob::BatchRecord.all.size
8
8
  cron_entries_count = GoodJob::CronEntry.all.size
9
9
  processes_count = GoodJob::Process.active.count
10
10
 
@@ -3,21 +3,17 @@
3
3
  module GoodJob
4
4
  class PerformancesController < ApplicationController
5
5
  def show
6
- if GoodJob::DiscreteExecution.duration_interval_migrated?
7
- @performances = GoodJob::DiscreteExecution
8
- .where.not(job_class: nil)
9
- .group(:job_class)
10
- .select("
6
+ @performances = GoodJob::DiscreteExecution
7
+ .where.not(job_class: nil)
8
+ .group(:job_class)
9
+ .select("
11
10
  job_class,
12
11
  COUNT(*) AS executions_count,
13
12
  AVG(duration) AS avg_duration,
14
13
  MIN(duration) AS min_duration,
15
14
  MAX(duration) AS max_duration
16
15
  ")
17
- .order("job_class")
18
- else
19
- @needs_upgrade = true
20
- end
16
+ .order("job_class")
21
17
  end
22
18
  end
23
19
  end
@@ -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, ' '), ''))" if labels_migrated?})"
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, ' '), '')))"
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')
@@ -74,9 +74,6 @@ module GoodJob
74
74
  end
75
75
  end
76
76
 
77
- belongs_to :batch, class_name: 'GoodJob::BatchRecord', optional: true, inverse_of: :executions
78
- has_many :discrete_executions, class_name: 'GoodJob::DiscreteExecution', foreign_key: 'active_job_id', primary_key: 'active_job_id', inverse_of: :execution # rubocop:disable Rails/HasManyOrHasOneDependent
79
-
80
77
  # With a given class name
81
78
  # @!method job_class(name)
82
79
  # @!scope class
@@ -84,11 +81,6 @@ module GoodJob
84
81
  # @return [ActiveRecord::Relation]
85
82
  scope :job_class, ->(name) { where(params_job_class.eq(name)) }
86
83
 
87
- after_destroy lambda {
88
- GoodJob::DiscreteExecution.where(active_job_id: active_job_id).delete_all if discrete? # TODO: move into association `dependent: :delete_all` after v4
89
- self.class.active_job_id(active_job_id).delete_all
90
- }, if: -> { @_destroy_job }
91
-
92
84
  # Get jobs with given ActiveJob ID
93
85
  # @!method active_job_id(active_job_id)
94
86
  # @!scope class
@@ -226,67 +218,12 @@ module GoodJob
226
218
  end
227
219
 
228
220
  def discrete_support?
229
- GoodJob::DiscreteExecution.migrated?
230
- end
231
-
232
- def error_event_migrated?
233
- return true if columns_hash["error_event"].present?
234
-
235
- migration_pending_warning!
236
- false
237
- end
238
-
239
- def cron_indices_migrated?
240
- return true if connection.index_name_exists?(:good_jobs, :index_good_jobs_on_cron_key_and_created_at_cond)
241
-
242
- migration_pending_warning!
243
- false
244
- end
245
-
246
- def labels_migrated?
247
- return true if columns_hash["labels"].present?
248
-
249
- migration_pending_warning!
250
- false
251
- end
252
-
253
- def labels_indices_migrated?
254
- return true if connection.index_name_exists?(:good_jobs, :index_good_jobs_on_labels)
255
-
256
- migration_pending_warning!
257
- false
221
+ true
258
222
  end
259
-
260
- def active_job_id_index_removal_migrated?
261
- return true unless connection.index_name_exists?(:good_jobs, :index_good_jobs_on_active_job_id)
262
-
263
- migration_pending_warning!
264
- false
265
- end
266
-
267
- def candidate_lookup_index_migrated?
268
- return true if connection.index_name_exists?(:good_jobs, :index_good_job_jobs_for_candidate_lookup)
269
-
270
- migration_pending_warning!
271
- false
272
- end
273
-
274
- def process_lock_migrated?
275
- return true if connection.index_name_exists?(:good_job_executions, :index_good_job_executions_on_process_id_and_created_at)
276
-
277
- migration_pending_warning!
278
- false
279
- end
280
- end
281
-
282
- # The ActiveJob job class, as a string
283
- # @return [String]
284
- def job_class
285
- discrete? ? attributes['job_class'] : serialized_params['job_class']
286
223
  end
287
224
 
288
225
  def discrete?
289
- self.class.discrete_support? && is_discrete?
226
+ is_discrete?
290
227
  end
291
228
 
292
229
  # Build an ActiveJob instance and deserialize the arguments, using `#active_job_data`.
@@ -304,54 +241,54 @@ module GoodJob
304
241
  raise unless ignore_deserialization_errors
305
242
  end
306
243
 
307
- def self.build_for_enqueue(active_job, overrides = {})
308
- new(**enqueue_args(active_job, overrides))
244
+ def self.build_for_enqueue(active_job, scheduled_at: nil)
245
+ new(**enqueue_args(active_job, scheduled_at: scheduled_at))
309
246
  end
310
247
 
311
248
  # Construct arguments for GoodJob::Execution from an ActiveJob instance.
312
- def self.enqueue_args(active_job, overrides = {})
313
- if active_job.priority && GoodJob.configuration.smaller_number_is_higher_priority.in?([nil, false])
314
- GoodJob.deprecator.warn(<<~DEPRECATION)
315
- The next major version of GoodJob (v4.0) will change job `priority` to give smaller numbers higher priority (default: `0`), in accordance with Active Job's definition of priority.
316
- To opt-in to this behavior now, set `config.good_job.smaller_number_is_higher_priority = true` in your GoodJob initializer or application.rb.
317
- DEPRECATION
318
- end
319
-
249
+ def self.enqueue_args(active_job, scheduled_at: nil)
320
250
  execution_args = {
251
+ id: active_job.job_id,
321
252
  active_job_id: active_job.job_id,
253
+ job_class: active_job.class.name,
322
254
  queue_name: active_job.queue_name.presence || DEFAULT_QUEUE_NAME,
323
255
  priority: active_job.priority || DEFAULT_PRIORITY,
324
256
  serialized_params: active_job.serialize,
257
+ created_at: Time.current,
325
258
  }
326
- execution_args[:scheduled_at] = Time.zone.at(active_job.scheduled_at) if active_job.scheduled_at
259
+
260
+ execution_args[:scheduled_at] = if scheduled_at
261
+ scheduled_at
262
+ elsif active_job.scheduled_at
263
+ Time.zone.at(active_job.scheduled_at)
264
+ else
265
+ execution_args[:created_at]
266
+ end
267
+
327
268
  execution_args[:concurrency_key] = active_job.good_job_concurrency_key if active_job.respond_to?(:good_job_concurrency_key)
328
269
 
329
- if active_job.respond_to?(:good_job_labels) && active_job.good_job_labels.any? && labels_migrated?
270
+ if active_job.respond_to?(:good_job_labels) && active_job.good_job_labels.any?
330
271
  labels = active_job.good_job_labels.dup
331
272
  labels.map! { |label| label.to_s.strip.presence }
332
273
  labels.tap(&:compact!).tap(&:uniq!)
333
274
  execution_args[:labels] = labels
334
275
  end
335
276
 
336
- reenqueued_current_execution = CurrentThread.active_job_id && CurrentThread.active_job_id == active_job.job_id
337
- current_execution = CurrentThread.execution
277
+ reenqueued_current_job = CurrentThread.active_job_id && CurrentThread.active_job_id == active_job.job_id
278
+ current_job = CurrentThread.job
338
279
 
339
- if reenqueued_current_execution
340
- if GoodJob::BatchRecord.migrated?
341
- execution_args[:batch_id] = current_execution.batch_id
342
- execution_args[:batch_callback_id] = current_execution.batch_callback_id
343
- end
344
- execution_args[:cron_key] = current_execution.cron_key
280
+ if reenqueued_current_job
281
+ execution_args[:batch_id] = current_job.batch_id
282
+ execution_args[:batch_callback_id] = current_job.batch_callback_id
283
+ execution_args[:cron_key] = current_job.cron_key
345
284
  else
346
- if GoodJob::BatchRecord.migrated?
347
- execution_args[:batch_id] = GoodJob::Batch.current_batch_id
348
- execution_args[:batch_callback_id] = GoodJob::Batch.current_batch_callback_id
349
- end
285
+ execution_args[:batch_id] = GoodJob::Batch.current_batch_id
286
+ execution_args[:batch_callback_id] = GoodJob::Batch.current_batch_callback_id
350
287
  execution_args[:cron_key] = CurrentThread.cron_key
351
288
  execution_args[:cron_at] = CurrentThread.cron_at
352
289
  end
353
290
 
354
- execution_args.merge(overrides)
291
+ execution_args
355
292
  end
356
293
 
357
294
  # Finds the next eligible Execution, acquire an advisory lock related to it, and
@@ -363,21 +300,23 @@ module GoodJob
363
300
  # raised, if any (if the job raised, then the second array entry will be
364
301
  # +nil+). If there were no jobs to execute, returns +nil+.
365
302
  def self.perform_with_advisory_lock(lock_id:, parsed_queues: nil, queue_select_limit: nil)
366
- execution = nil
303
+ job = nil
367
304
  result = nil
368
305
 
369
- unfinished.dequeueing_ordered(parsed_queues).only_scheduled.limit(1).with_advisory_lock(select_limit: queue_select_limit) do |executions|
370
- execution = executions.first
371
- if execution&.executable?
372
- yield(execution) if block_given?
373
- result = execution.perform(lock_id: lock_id)
306
+ unfinished.dequeueing_ordered(parsed_queues).only_scheduled.limit(1).with_advisory_lock(select_limit: queue_select_limit) do |jobs|
307
+ job = jobs.first
308
+
309
+ if job&.executable?
310
+ yield(job) if block_given?
311
+
312
+ result = job.perform(lock_id: lock_id)
374
313
  else
375
- execution = nil
314
+ job = nil
376
315
  yield(nil) if block_given?
377
316
  end
378
317
  end
379
318
 
380
- execution&.run_callbacks(:perform_unlocked)
319
+ job&.run_callbacks(:perform_unlocked)
381
320
  result
382
321
  end
383
322
 
@@ -413,46 +352,38 @@ module GoodJob
413
352
  # The new {Execution} instance representing the queued ActiveJob job.
414
353
  def self.enqueue(active_job, scheduled_at: nil, create_with_advisory_lock: false)
415
354
  ActiveSupport::Notifications.instrument("enqueue_job.good_job", { active_job: active_job, scheduled_at: scheduled_at, create_with_advisory_lock: create_with_advisory_lock }) do |instrument_payload|
416
- current_execution = CurrentThread.execution
355
+ current_job = CurrentThread.job
417
356
 
418
- retried = current_execution && current_execution.active_job_id == active_job.job_id
357
+ retried = current_job && current_job.active_job_id == active_job.job_id
419
358
  if retried
420
- if current_execution.discrete?
421
- execution = current_execution
422
- execution.assign_attributes(enqueue_args(active_job, { scheduled_at: scheduled_at }))
423
- execution.scheduled_at ||= Time.current
424
- # TODO: these values ideally shouldn't be persisted until the current_execution is finished
425
- # which will require handling `retry_job` being called from outside the execution context.
426
- execution.performed_at = nil
427
- execution.finished_at = nil
428
- else
429
- execution = build_for_enqueue(active_job, { scheduled_at: scheduled_at })
430
- end
359
+ job = current_job
360
+ job.assign_attributes(enqueue_args(active_job, scheduled_at: scheduled_at))
361
+ job.scheduled_at ||= Time.current
362
+ # TODO: these values ideally shouldn't be persisted until the current_job is finished
363
+ # which will require handling `retry_job` being called from outside the job context.
364
+ job.performed_at = nil
365
+ job.finished_at = nil
431
366
  else
432
- execution = build_for_enqueue(active_job, { scheduled_at: scheduled_at })
433
- execution.make_discrete if discrete_support?
367
+ job = build_for_enqueue(active_job, scheduled_at: scheduled_at)
434
368
  end
435
369
 
436
370
  if create_with_advisory_lock
437
- if execution.persisted?
438
- execution.advisory_lock
371
+ if job.persisted?
372
+ job.advisory_lock
439
373
  else
440
- execution.create_with_advisory_lock = true
374
+ job.create_with_advisory_lock = true
441
375
  end
442
376
  end
443
377
 
444
- instrument_payload[:execution] = execution
445
- execution.save!
378
+ instrument_payload[:job] = job
379
+ job.save!
446
380
 
447
- if retried
448
- CurrentThread.execution_retried = execution
449
- CurrentThread.execution.retried_good_job_id = execution.id unless current_execution.discrete?
450
- else
451
- CurrentThread.execution_retried = nil
452
- end
381
+ CurrentThread.execution_retried = (job if retried)
453
382
 
454
- active_job.provider_job_id = execution.id
455
- execution
383
+ active_job.provider_job_id = job.id
384
+ raise "These should be equal" if active_job.provider_job_id != active_job.job_id
385
+
386
+ job
456
387
  end
457
388
  end
458
389
 
@@ -476,64 +407,47 @@ module GoodJob
476
407
  discrete_execution = nil
477
408
  result = GoodJob::CurrentThread.within do |current_thread|
478
409
  current_thread.reset
479
- current_thread.execution = self
410
+ current_thread.job = self
480
411
 
481
412
  existing_performed_at = performed_at
482
413
  if existing_performed_at
483
414
  current_thread.execution_interrupted = existing_performed_at
484
415
 
485
- if discrete?
486
- interrupt_error_string = self.class.format_error(GoodJob::InterruptError.new("Interrupted after starting perform at '#{existing_performed_at}'"))
487
- self.error = interrupt_error_string
488
- self.error_event = ERROR_EVENT_INTERRUPTED if self.class.error_event_migrated?
489
- monotonic_duration = (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - monotonic_start).seconds
490
-
491
- discrete_execution_attrs = {
492
- error: interrupt_error_string,
493
- finished_at: job_performed_at,
494
- }
495
- discrete_execution_attrs[:error_event] = GoodJob::ErrorEvents::ERROR_EVENT_ENUMS[GoodJob::ErrorEvents::ERROR_EVENT_INTERRUPTED] if self.class.error_event_migrated?
496
- discrete_execution_attrs[:duration] = monotonic_duration if GoodJob::DiscreteExecution.duration_interval_usable?
497
- discrete_executions.where(finished_at: nil).where.not(performed_at: nil).update_all(discrete_execution_attrs) # rubocop:disable Rails/SkipsModelValidations
498
- end
416
+ interrupt_error_string = self.class.format_error(GoodJob::InterruptError.new("Interrupted after starting perform at '#{existing_performed_at}'"))
417
+ self.error = interrupt_error_string
418
+ self.error_event = ERROR_EVENT_INTERRUPTED
419
+ monotonic_duration = (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - monotonic_start).seconds
420
+
421
+ discrete_execution_attrs = {
422
+ error: interrupt_error_string,
423
+ finished_at: job_performed_at,
424
+ }
425
+ discrete_execution_attrs[:error_event] = GoodJob::ErrorEvents::ERROR_EVENT_ENUMS[GoodJob::ErrorEvents::ERROR_EVENT_INTERRUPTED]
426
+ discrete_execution_attrs[:duration] = monotonic_duration
427
+ discrete_executions.where(finished_at: nil).where.not(performed_at: nil).update_all(discrete_execution_attrs) # rubocop:disable Rails/SkipsModelValidations
499
428
  end
500
429
 
501
- if discrete?
502
- transaction do
503
- discrete_execution_attrs = {
504
- job_class: job_class,
505
- queue_name: queue_name,
506
- serialized_params: serialized_params,
507
- scheduled_at: (scheduled_at || created_at),
508
- created_at: job_performed_at,
509
- }
510
- discrete_execution_attrs[:process_id] = lock_id if GoodJob::DiscreteExecution.columns_hash.key?("process_id")
511
-
512
- execution_attrs = {
513
- performed_at: job_performed_at,
514
- executions_count: ((executions_count || 0) + 1),
515
- }
516
- if GoodJob::Execution.columns_hash.key?("locked_by_id")
517
- execution_attrs[:locked_by_id] = lock_id
518
- execution_attrs[:locked_at] = Time.current
519
- end
520
-
521
- discrete_execution = discrete_executions.create!(discrete_execution_attrs)
522
- update!(execution_attrs)
523
- end
524
- else
525
- execution_attrs = {
430
+ transaction do
431
+ discrete_execution_attrs = {
432
+ job_class: job_class,
433
+ queue_name: queue_name,
434
+ serialized_params: serialized_params,
435
+ scheduled_at: (scheduled_at || created_at),
436
+ created_at: job_performed_at,
437
+ process_id: lock_id,
438
+ }
439
+ job_attrs = {
526
440
  performed_at: job_performed_at,
441
+ executions_count: ((executions_count || 0) + 1),
442
+ locked_by_id: lock_id,
443
+ locked_at: Time.current,
527
444
  }
528
- if GoodJob::Execution.columns_hash.key?("locked_by_id")
529
- execution_attrs[:locked_by_id] = lock_id
530
- execution_attrs[:locked_at] = Time.current
531
- end
532
445
 
533
- update!(execution_attrs)
446
+ discrete_execution = discrete_executions.create!(discrete_execution_attrs)
447
+ update!(job_attrs)
534
448
  end
535
449
 
536
- ActiveSupport::Notifications.instrument("perform_job.good_job", { execution: self, process_id: current_thread.process_id, thread_name: current_thread.thread_name }) do |instrument_payload|
450
+ ActiveSupport::Notifications.instrument("perform_job.good_job", { job: self, execution: discrete_execution, process_id: current_thread.process_id, thread_name: current_thread.thread_name }) do |instrument_payload|
537
451
  value = ActiveJob::Base.execute(active_job_data)
538
452
 
539
453
  if value.is_a?(Exception)
@@ -584,50 +498,39 @@ module GoodJob
584
498
  error_string = self.class.format_error(job_error)
585
499
 
586
500
  job_attributes[:error] = error_string
587
- job_attributes[:error_event] = result.error_event if self.class.error_event_migrated?
588
- if discrete_execution
589
- discrete_execution.error = error_string
590
- discrete_execution.error_event = result.error_event
591
- discrete_execution.error_backtrace = job_error.backtrace if discrete_execution.class.backtrace_migrated?
592
- end
501
+ job_attributes[:error_event] = result.error_event
502
+
503
+ discrete_execution.error = error_string
504
+ discrete_execution.error_event = result.error_event
505
+ discrete_execution.error_backtrace = job_error.backtrace
593
506
  else
594
507
  job_attributes[:error] = nil
595
508
  job_attributes[:error_event] = nil
596
509
  end
597
- job_attributes.delete(:error_event) unless self.class.error_event_migrated?
598
510
 
599
511
  job_finished_at = Time.current
600
512
  monotonic_duration = (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - monotonic_start).seconds
601
513
  job_attributes[:finished_at] = job_finished_at
602
- if discrete_execution
603
- discrete_execution.finished_at = job_finished_at
604
- discrete_execution.duration = monotonic_duration if GoodJob::DiscreteExecution.duration_interval_usable?
605
- end
514
+
515
+ discrete_execution.finished_at = job_finished_at
516
+ discrete_execution.duration = monotonic_duration
606
517
 
607
518
  retry_unhandled_error = result.unhandled_error && GoodJob.retry_on_unhandled_error
608
519
  reenqueued = result.retried? || retried_good_job_id.present? || retry_unhandled_error
609
520
  if reenqueued
610
- if discrete_execution
611
- job_attributes[:performed_at] = nil
612
- job_attributes[:finished_at] = nil
613
- else
614
- job_attributes[:retried_good_job_id] = retried_good_job_id
615
- job_attributes[:finished_at] = nil if retry_unhandled_error
616
- end
521
+ job_attributes[:performed_at] = nil
522
+ job_attributes[:finished_at] = nil
617
523
  end
618
524
 
525
+ assign_attributes(job_attributes)
619
526
  preserve_unhandled = (result.unhandled_error && (GoodJob.retry_on_unhandled_error || GoodJob.preserve_job_records == :on_unhandled_error))
620
- if GoodJob.preserve_job_records == true || reenqueued || preserve_unhandled || cron_key.present?
621
- if discrete_execution
622
- transaction do
623
- discrete_execution.save!
624
- update!(job_attributes)
625
- end
626
- else
627
- update!(job_attributes)
527
+ if finished_at.blank? || GoodJob.preserve_job_records == true || reenqueued || preserve_unhandled || cron_key.present?
528
+ transaction do
529
+ discrete_execution.save!
530
+ save!
628
531
  end
629
532
  else
630
- destroy_job
533
+ destroy!
631
534
  end
632
535
 
633
536
  result
@@ -708,7 +611,7 @@ module GoodJob
708
611
  end
709
612
 
710
613
  def continue_discard_or_finish_batch
711
- batch._continue_discard_or_finish(self) if GoodJob::BatchRecord.migrated? && batch.present?
614
+ batch._continue_discard_or_finish(self) if batch.present?
712
615
  end
713
616
 
714
617
  def active_job_data
@@ -716,7 +619,7 @@ module GoodJob
716
619
  .tap do |job_data|
717
620
  job_data["provider_job_id"] = id
718
621
  job_data["good_job_concurrency_key"] = concurrency_key if concurrency_key
719
- job_data["good_job_labels"] = Array(labels) if self.class.labels_migrated? && labels.present?
622
+ job_data["good_job_labels"] = Array(labels) if labels.present?
720
623
  end
721
624
  end
722
625
  end
@@ -72,8 +72,6 @@ module GoodJob # :nodoc:
72
72
  end
73
73
 
74
74
  def enabled?
75
- return true unless GoodJob::Setting.migrated?
76
-
77
75
  GoodJob::Setting.cron_key_enabled?(key, default: enabled_by_default?)
78
76
  end
79
77