good_job 3.99.1 → 4.0.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.
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
@@ -11,7 +11,6 @@ it:
11
11
  batches:
12
12
  index:
13
13
  older_batches: Batch più vecchi
14
- pending_migrations: GoodJob ha migrazioni del database in sospeso.
15
14
  title: Batch
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ it:
48
47
  index:
49
48
  no_cron_schedules_found: Nessuna pianificazione cron trovata.
50
49
  title: Pianificazioni cron
51
- pending_migrations: Richiede migrazione del database GoodJob in sospeso.
52
50
  show:
53
51
  cron_entry_key: Chiave voce cron
54
52
  datetime:
@@ -240,6 +238,7 @@ it:
240
238
  dark: Scuro
241
239
  light: Chiaro
242
240
  theme: Tema
241
+ pending_migrations: GoodJob ha migrazioni del database in sospeso.
243
242
  secondary_navbar:
244
243
  inspiration: Ricorda, stai facendo anche tu un Buon Lavoro!
245
244
  last_updated: Ultimo aggiornamento
@@ -250,5 +249,3 @@ it:
250
249
  running: In esecuzione
251
250
  scheduled: Pianificato
252
251
  succeeded: Riuscito
253
- shared:
254
- needs_migration: Esegui le migrazioni GoodJob.
@@ -11,7 +11,6 @@ ja:
11
11
  batches:
12
12
  index:
13
13
  older_batches: より古いバッチ
14
- pending_migrations: GoodJobに保留中のデータベースマイグレーションがあります。
15
14
  title: バッチ
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ ja:
48
47
  index:
49
48
  no_cron_schedules_found: cronスケジュールが見つかりませんでした。
50
49
  title: cronスケジュール
51
- pending_migrations: GoodJobの保留中のデータベースマイグレーションが必要です。
52
50
  show:
53
51
  cron_entry_key: cronエントリキー
54
52
  datetime:
@@ -240,6 +238,7 @@ ja:
240
238
  dark: 暗い
241
239
  light: ライト
242
240
  theme: テーマ
241
+ pending_migrations: GoodJobに保留中のデータベースマイグレーションがあります。
243
242
  secondary_navbar:
244
243
  inspiration: 覚えておいてください、あなたも良い仕事をしています!
245
244
  last_updated: 最終更新
@@ -250,5 +249,3 @@ ja:
250
249
  running: 実行中
251
250
  scheduled: スケジュール待ち
252
251
  succeeded: 成功済み
253
- shared:
254
- needs_migration: GoodJob 移行を実行してください。
@@ -11,7 +11,6 @@ ko:
11
11
  batches:
12
12
  index:
13
13
  older_batches: 더 오래된 배치
14
- pending_migrations: GoodJob에 보류 중인 데이터베이스 마이그레이션 작업이 있습니다.
15
14
  title: 배치
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ ko:
48
47
  index:
49
48
  no_cron_schedules_found: cron 스케줄을 찾을 수 없습니다.
50
49
  title: cron 스케줄
51
- pending_migrations: 보류 중인 GoodJob 데이터베이스 마이그레이션이 필요합니다.
52
50
  show:
53
51
  cron_entry_key: cron 엔트리 키
54
52
  datetime:
@@ -240,6 +238,7 @@ ko:
240
238
  dark: 어두운
241
239
  light: 밝은
242
240
  theme: 테마
241
+ pending_migrations: GoodJob에 보류 중인 데이터베이스 마이그레이션 작업이 있습니다.
243
242
  secondary_navbar:
244
243
  inspiration: 기억하세요, 당신도 좋은 일을 하고 있습니다!
245
244
  last_updated: 최종 업데이트
@@ -250,5 +249,3 @@ ko:
250
249
  running: 실행 중
251
250
  scheduled: 예정됨
252
251
  succeeded: 성공함
253
- shared:
254
- needs_migration: GoodJob 마이그레이션을 실행하세요.
@@ -11,7 +11,6 @@ nl:
11
11
  batches:
12
12
  index:
13
13
  older_batches: Oudere partijen
14
- pending_migrations: GoodJob heeft databasemigraties in behandeling.
15
14
  title: Partijen
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ nl:
48
47
  index:
49
48
  no_cron_schedules_found: Geen cron-schema's gevonden.
50
49
  title: Cron-schema's
51
- pending_migrations: Vereist GoodJob-databasemigratie in afwachting.
52
50
  show:
53
51
  cron_entry_key: Cron-invoersleutel
54
52
  datetime:
@@ -240,6 +238,7 @@ nl:
240
238
  dark: Donker
241
239
  light: Licht
242
240
  theme: Thema
241
+ pending_migrations: GoodJob heeft databasemigraties in behandeling.
243
242
  secondary_navbar:
244
243
  inspiration: 'Onthoud: jij levert ook goed werk!'
245
244
  last_updated: Laatst bijgewerkt
@@ -250,5 +249,3 @@ nl:
250
249
  running: Rennen
251
250
  scheduled: Gepland
252
251
  succeeded: Geslaagd
253
- shared:
254
- needs_migration: Voer GoodJob-migraties uit.
@@ -11,7 +11,6 @@ pt-BR:
11
11
  batches:
12
12
  index:
13
13
  older_batches: Lotes antigos
14
- pending_migrations: O GoodJob tem migrações pendentes no banco de dados.
15
14
  title: Lotes
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ pt-BR:
48
47
  index:
49
48
  no_cron_schedules_found: Nenhuma tarefa programada encontrada.
50
49
  title: Tarefas Programadas
51
- pending_migrations: Requer migração pendente do GoodJob no banco de dados.
52
50
  show:
53
51
  cron_entry_key: Chave da Tarefa Programada
54
52
  datetime:
@@ -240,6 +238,7 @@ pt-BR:
240
238
  dark: Escuro
241
239
  light: Claro
242
240
  theme: Tema
241
+ pending_migrations: O GoodJob tem migrações pendentes no banco de dados.
243
242
  secondary_navbar:
244
243
  inspiration: Lembre-se, você também está fazendo uma Boa Tarefa!
245
244
  last_updated: Última atualização
@@ -250,5 +249,3 @@ pt-BR:
250
249
  running: Em execução
251
250
  scheduled: Agendado
252
251
  succeeded: Concluído com sucesso
253
- shared:
254
- needs_migration: Execute migrações GoodJob.
@@ -11,7 +11,6 @@ ru:
11
11
  batches:
12
12
  index:
13
13
  older_batches: Старые группы заданий
14
- pending_migrations: У GoodJob есть ожидающие миграции базы данных.
15
14
  title: Группы заданий
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ ru:
48
47
  index:
49
48
  no_cron_schedules_found: Расписания cron не найдены.
50
49
  title: Расписания cron
51
- pending_migrations: У GoodJob есть ожидающие миграции базы данных.
52
50
  show:
53
51
  cron_entry_key: Ключ cron-задания
54
52
  datetime:
@@ -266,6 +264,7 @@ ru:
266
264
  dark: Темный
267
265
  light: Светлая
268
266
  theme: Тема офрмдления
267
+ pending_migrations: У GoodJob есть ожидающие миграции базы данных.
269
268
  secondary_navbar:
270
269
  inspiration: Благодаря вам Good Job становится лучше! Спасибо!
271
270
  last_updated: Последнее обновление
@@ -276,5 +275,3 @@ ru:
276
275
  running: Исполняется
277
276
  scheduled: Запланировано
278
277
  succeeded: Успешно
279
- shared:
280
- needs_migration: Пожалуйста, запустите миграцию GoodJob.
@@ -11,7 +11,6 @@ tr:
11
11
  batches:
12
12
  index:
13
13
  older_batches: Daha eski toplu işlemler
14
- pending_migrations: GoodJob'ın bekleyen veritabanı güncellemeleri bulunuyor.
15
14
  title: Toplu İşlemler
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ tr:
48
47
  index:
49
48
  no_cron_schedules_found: Planlanmış Cron bulunamadı.
50
49
  title: Cron Planları
51
- pending_migrations: Bekleyen GoodJob veritabanı güncellemesi var.
52
50
  show:
53
51
  cron_entry_key: Cron Giriş Anahtarı
54
52
  datetime:
@@ -240,6 +238,7 @@ tr:
240
238
  dark: Karanlık
241
239
  light: Işık
242
240
  theme: Tema
241
+ pending_migrations: GoodJob'ın bekleyen veritabanı güncellemeleri bulunuyor.
243
242
  secondary_navbar:
244
243
  inspiration: Unutmayın, siz de iyi bir iş yapıyorsunuz!
245
244
  last_updated: Son güncelleme
@@ -250,5 +249,3 @@ tr:
250
249
  running: Çalışıyor
251
250
  scheduled: Planlandı
252
251
  succeeded: Başarılı
253
- shared:
254
- needs_migration: Lütfen GoodJob geçişlerini çalıştırın.
@@ -11,7 +11,6 @@ uk:
11
11
  batches:
12
12
  index:
13
13
  older_batches: Старі пакети
14
- pending_migrations: GoodJob має невиконані міграції бази даних.
15
14
  title: Пакети
16
15
  jobs:
17
16
  actions:
@@ -48,7 +47,6 @@ uk:
48
47
  index:
49
48
  no_cron_schedules_found: Cron-розклади не знайдені.
50
49
  title: Cron-розклади
51
- pending_migrations: Вимагає невиконаних міграцій бази даних GoodJob.
52
50
  show:
53
51
  cron_entry_key: Ключ cron-запису
54
52
  datetime:
@@ -266,6 +264,7 @@ uk:
266
264
  dark: Темний
267
265
  light: світло
268
266
  theme: Тема
267
+ pending_migrations: GoodJob має невиконані міграції бази даних.
269
268
  secondary_navbar:
270
269
  inspiration: Пам'ятайте, ви теж робите хорошу роботу!
271
270
  last_updated: Останнє оновлення
@@ -276,5 +275,3 @@ uk:
276
275
  running: Виконується
277
276
  scheduled: Заплановано
278
277
  succeeded: Успішно виконано
279
- shared:
280
- needs_migration: Запустіть міграції GoodJob.
@@ -21,20 +21,82 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
21
21
  t.text :cron_key
22
22
  t.uuid :retried_good_job_id
23
23
  t.datetime :cron_at
24
+
25
+ t.uuid :batch_id
26
+ t.uuid :batch_callback_id
27
+
28
+ t.boolean :is_discrete
29
+ t.integer :executions_count
30
+ t.text :job_class
31
+ t.integer :error_event, limit: 2
32
+ t.text :labels, array: true
33
+ t.uuid :locked_by_id
34
+ t.datetime :locked_at
35
+ end
36
+
37
+ create_table :good_job_batches, id: :uuid do |t|
38
+ t.timestamps
39
+ t.text :description
40
+ t.jsonb :serialized_properties
41
+ t.text :on_finish
42
+ t.text :on_success
43
+ t.text :on_discard
44
+ t.text :callback_queue_name
45
+ t.integer :callback_priority
46
+ t.datetime :enqueued_at
47
+ t.datetime :discarded_at
48
+ t.datetime :finished_at
49
+ end
50
+
51
+ create_table :good_job_executions, id: :uuid do |t|
52
+ t.timestamps
53
+
54
+ t.uuid :active_job_id, null: false
55
+ t.text :job_class
56
+ t.text :queue_name
57
+ t.jsonb :serialized_params
58
+ t.datetime :scheduled_at
59
+ t.datetime :finished_at
60
+ t.text :error
61
+ t.integer :error_event, limit: 2
62
+ t.text :error_backtrace, array: true
63
+ t.uuid :process_id
64
+ t.interval :duration
24
65
  end
25
66
 
26
67
  create_table :good_job_processes, id: :uuid do |t|
27
68
  t.timestamps
28
69
  t.jsonb :state
70
+ t.integer :lock_type, limit: 2
71
+ end
72
+
73
+ create_table :good_job_settings, id: :uuid do |t|
74
+ t.timestamps
75
+ t.text :key
76
+ t.jsonb :value
77
+ t.index :key, unique: true
29
78
  end
30
79
 
31
80
  add_index :good_jobs, :scheduled_at, where: "(finished_at IS NULL)", name: :index_good_jobs_on_scheduled_at
32
81
  add_index :good_jobs, [:queue_name, :scheduled_at], where: "(finished_at IS NULL)", name: :index_good_jobs_on_queue_name_and_scheduled_at
33
82
  add_index :good_jobs, [:active_job_id, :created_at], name: :index_good_jobs_on_active_job_id_and_created_at
34
83
  add_index :good_jobs, :concurrency_key, where: "(finished_at IS NULL)", name: :index_good_jobs_on_concurrency_key_when_unfinished
35
- add_index :good_jobs, [:cron_key, :created_at], name: :index_good_jobs_on_cron_key_and_created_at
36
- add_index :good_jobs, [:cron_key, :cron_at], name: :index_good_jobs_on_cron_key_and_cron_at, unique: true
37
- add_index :good_jobs, [:active_job_id], name: :index_good_jobs_on_active_job_id
84
+ add_index :good_jobs, [:cron_key, :created_at], where: "(cron_key IS NOT NULL)", name: :index_good_jobs_on_cron_key_and_created_at_cond
85
+ add_index :good_jobs, [:cron_key, :cron_at], where: "(cron_key IS NOT NULL)", unique: true, name: :index_good_jobs_on_cron_key_and_cron_at_cond
38
86
  add_index :good_jobs, [:finished_at], where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at
87
+ add_index :good_jobs, [:priority, :created_at], order: { priority: "DESC NULLS LAST", created_at: :asc },
88
+ where: "finished_at IS NULL", name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished
89
+ add_index :good_jobs, [:priority, :created_at], order: { priority: "ASC NULLS LAST", created_at: :asc },
90
+ where: "finished_at IS NULL", name: :index_good_job_jobs_for_candidate_lookup
91
+ add_index :good_jobs, [:batch_id], where: "batch_id IS NOT NULL"
92
+ add_index :good_jobs, [:batch_callback_id], where: "batch_callback_id IS NOT NULL"
93
+ add_index :good_jobs, :labels, using: :gin, where: "(labels IS NOT NULL)", name: :index_good_jobs_on_labels
94
+
95
+ add_index :good_job_executions, [:active_job_id, :created_at], name: :index_good_job_executions_on_active_job_id_and_created_at
96
+ add_index :good_jobs, [:priority, :scheduled_at], order: { priority: "ASC NULLS LAST", scheduled_at: :asc },
97
+ where: "finished_at IS NULL AND locked_by_id IS NULL", name: :index_good_jobs_on_priority_scheduled_at_unfinished_unlocked
98
+ add_index :good_jobs, :locked_by_id,
99
+ where: "locked_by_id IS NOT NULL", name: "index_good_jobs_on_locked_by_id"
100
+ add_index :good_job_executions, [:process_id, :created_at], name: :index_good_job_executions_on_process_id_and_created_at
39
101
  end
40
102
  end
@@ -12,7 +12,7 @@ module GoodJob
12
12
  end
13
13
 
14
14
  def batch
15
- @_batch ||= CurrentThread.execution&.batch&.to_batch if CurrentThread.execution.present? && CurrentThread.execution.active_job_id == job_id
15
+ @_batch ||= CurrentThread.job&.batch&.to_batch if CurrentThread.job.present? && CurrentThread.job.active_job_id == job_id
16
16
  end
17
17
  alias batch? batch
18
18
  end
@@ -66,7 +66,7 @@ module GoodJob
66
66
 
67
67
  perform_throttle = job.class.good_job_concurrency_config[:perform_throttle]
68
68
  perform_throttle = instance_exec(&perform_throttle) if perform_throttle.respond_to?(:call)
69
- perform_throttle = nil unless GoodJob::DiscreteExecution.migrated? && perform_throttle.present? && perform_throttle.is_a?(Array) && perform_throttle.size == 2
69
+ perform_throttle = nil unless perform_throttle.present? && perform_throttle.is_a?(Array) && perform_throttle.size == 2
70
70
 
71
71
  limit = perform_limit || total_limit
72
72
  throttle = perform_throttle
@@ -75,17 +75,17 @@ module GoodJob
75
75
  key = job.good_job_concurrency_key
76
76
  next if key.blank?
77
77
 
78
- if CurrentThread.execution.blank? || CurrentThread.execution.active_job_id != job_id
78
+ if CurrentThread.job.blank? || CurrentThread.job.active_job_id != job_id
79
79
  logger.debug("Ignoring concurrency limits because the job is executed with `perform_now`.")
80
80
  next
81
81
  end
82
82
 
83
- GoodJob::Execution.advisory_lock_key(key, function: "pg_advisory_lock") do
83
+ GoodJob::Job.advisory_lock_key(key, function: "pg_advisory_lock") do
84
84
  if limit
85
- allowed_active_job_ids = GoodJob::Execution.unfinished.where(concurrency_key: key)
86
- .advisory_locked
87
- .order(Arel.sql("COALESCE(performed_at, scheduled_at, created_at) ASC"))
88
- .limit(limit).pluck(:active_job_id)
85
+ allowed_active_job_ids = GoodJob::Job.unfinished.where(concurrency_key: key)
86
+ .advisory_locked
87
+ .order(Arel.sql("COALESCE(performed_at, scheduled_at, created_at) ASC"))
88
+ .limit(limit).pluck(:active_job_id)
89
89
  # The current job has already been locked and will appear in the previous query
90
90
  raise GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError unless allowed_active_job_ids.include?(job.job_id)
91
91
  end
@@ -172,12 +172,12 @@ module GoodJob
172
172
  throttle = enqueue_throttle
173
173
  return on_enqueue&.call unless limit || throttle
174
174
 
175
- GoodJob::Execution.advisory_lock_key(key, function: "pg_advisory_lock") do
175
+ GoodJob::Job.advisory_lock_key(key, function: "pg_advisory_lock") do
176
176
  if limit
177
177
  enqueue_concurrency = if enqueue_limit
178
- GoodJob::Execution.where(concurrency_key: key).unfinished.advisory_unlocked.count
178
+ GoodJob::Job.where(concurrency_key: key).unfinished.advisory_unlocked.count
179
179
  else
180
- GoodJob::Execution.where(concurrency_key: key).unfinished.count
180
+ GoodJob::Job.where(concurrency_key: key).unfinished.count
181
181
  end
182
182
 
183
183
  # The job has not yet been enqueued, so check if adding it will go over the limit
@@ -37,7 +37,7 @@ module GoodJob
37
37
  # Enqueues the ActiveJob job to be performed.
38
38
  # For use by Rails; you should generally not call this directly.
39
39
  # @param active_job [ActiveJob::Base] the job to be enqueued from +#perform_later+
40
- # @return [GoodJob::Execution]
40
+ # @return [GoodJob::Job]
41
41
  def enqueue(active_job)
42
42
  enqueue_at(active_job, nil)
43
43
  end
@@ -58,28 +58,17 @@ module GoodJob
58
58
  Rails.application.executor.wrap do
59
59
  current_time = Time.current
60
60
  executions = active_jobs.map do |active_job|
61
- GoodJob::Execution.build_for_enqueue(active_job).tap do |execution|
62
- if GoodJob::Execution.discrete_support?
63
- execution.make_discrete
64
- execution.scheduled_at = current_time if execution.scheduled_at == execution.created_at
65
- end
66
-
67
- execution.created_at = current_time
68
- execution.updated_at = current_time
61
+ GoodJob::Job.build_for_enqueue(active_job).tap do |job|
62
+ job.scheduled_at = current_time if job.scheduled_at == job.created_at
63
+ job.created_at = current_time
64
+ job.updated_at = current_time
69
65
  end
70
66
  end
71
67
 
72
68
  inline_executions = []
73
- GoodJob::Execution.transaction(requires_new: true, joinable: false) do
74
- execution_attributes = executions.map do |execution|
75
- if GoodJob::Execution.error_event_migrated?
76
- execution.attributes
77
- else
78
- execution.attributes.except('error_event')
79
- end
80
- end
81
-
82
- results = GoodJob::Execution.insert_all(execution_attributes, returning: %w[id active_job_id]) # rubocop:disable Rails/SkipsModelValidations
69
+ GoodJob::Job.transaction(requires_new: true, joinable: false) do
70
+ execution_attributes = executions.map(&:attributes)
71
+ results = GoodJob::Job.insert_all(execution_attributes, returning: %w[id active_job_id]) # rubocop:disable Rails/SkipsModelValidations
83
72
 
84
73
  job_id_to_provider_job_id = results.each_with_object({}) { |result, hash| hash[result['active_job_id']] = result['id'] }
85
74
  active_jobs.each do |active_job|
@@ -146,7 +135,7 @@ module GoodJob
146
135
  # For use by Rails; you should generally not call this directly.
147
136
  # @param active_job [ActiveJob::Base] the job to be enqueued from +#perform_later+
148
137
  # @param timestamp [Integer, nil] the epoch time to perform the job
149
- # @return [GoodJob::Execution]
138
+ # @return [GoodJob::Job]
150
139
  def enqueue_at(active_job, timestamp)
151
140
  scheduled_at = timestamp ? Time.zone.at(timestamp) : nil
152
141
 
@@ -156,15 +145,15 @@ module GoodJob
156
145
 
157
146
  Rails.application.executor.wrap do
158
147
  will_execute_inline = execute_inline? && (scheduled_at.nil? || scheduled_at <= Time.current)
159
- will_retry_inline = will_execute_inline && CurrentThread.execution&.active_job_id == active_job.job_id && !CurrentThread.retry_now
148
+ will_retry_inline = will_execute_inline && CurrentThread.job&.active_job_id == active_job.job_id && !CurrentThread.retry_now
160
149
 
161
150
  if will_retry_inline
162
- execution = GoodJob::Execution.enqueue(
151
+ execution = GoodJob::Job.enqueue(
163
152
  active_job,
164
153
  scheduled_at: scheduled_at
165
154
  )
166
155
  elsif will_execute_inline
167
- execution = GoodJob::Execution.enqueue(
156
+ execution = GoodJob::Job.enqueue(
168
157
  active_job,
169
158
  scheduled_at: scheduled_at,
170
159
  create_with_advisory_lock: true
@@ -186,7 +175,7 @@ module GoodJob
186
175
  end
187
176
  raise result.unhandled_error if result.unhandled_error
188
177
  else
189
- execution = GoodJob::Execution.enqueue(
178
+ execution = GoodJob::Job.enqueue(
190
179
  active_job,
191
180
  scheduled_at: scheduled_at
192
181
  )
@@ -13,7 +13,7 @@ module GoodJob
13
13
  error_on_discard
14
14
  error_on_retry
15
15
  error_on_retry_stopped
16
- execution
16
+ job
17
17
  execution_interrupted
18
18
  execution_retried
19
19
  retry_now
@@ -49,11 +49,11 @@ module GoodJob
49
49
  # @return [Exception, nil]
50
50
  thread_mattr_accessor :error_on_retry_stopped
51
51
 
52
- # @!attribute [rw] executions
52
+ # @!attribute [rw] jobs
53
53
  # @!scope class
54
54
  # Execution
55
- # @return [GoodJob::Execution, nil]
56
- thread_mattr_accessor :execution
55
+ # @return [GoodJob::Job, nil]
56
+ thread_mattr_accessor :job
57
57
 
58
58
  # @!attribute [rw] execution_interrupted
59
59
  # @!scope class
@@ -90,9 +90,9 @@ module GoodJob
90
90
  end
91
91
  end
92
92
 
93
- # @return [String] UUID of the currently executing GoodJob::Execution
93
+ # @return [String] UUID of the currently executing GoodJob::Job
94
94
  def self.active_job_id
95
- execution&.active_job_id
95
+ job&.active_job_id
96
96
  end
97
97
 
98
98
  # @return [Integer] Current process ID
@@ -108,11 +108,11 @@ module GoodJob
108
108
  attr_reader :queue_string
109
109
 
110
110
  def job_query
111
- @_job_query ||= GoodJob::Execution.queue_string(queue_string)
111
+ @_job_query ||= GoodJob::Job.queue_string(queue_string)
112
112
  end
113
113
 
114
114
  def parsed_queues
115
- @_parsed_queues ||= GoodJob::Execution.queue_parser(queue_string)
115
+ @_parsed_queues ||= GoodJob::Job.queue_parser(queue_string)
116
116
  end
117
117
  end
118
118
  end
@@ -18,14 +18,6 @@ module GoodJob
18
18
  # Responds to the +$0.good_job+ notification.
19
19
  # @param event [ActiveSupport::Notifications::Event]
20
20
  # @return [void]
21
- def create(event)
22
- # FIXME: This method does not match any good_job notifications.
23
- execution = event.payload[:execution]
24
-
25
- debug do
26
- "GoodJob created job resource with id #{execution.id}"
27
- end
28
- end
29
21
 
30
22
  # @!macro notification_responder
31
23
  def finished_timer_task(event)
@@ -110,12 +102,12 @@ module GoodJob
110
102
 
111
103
  # @!macro notification_responder
112
104
  def perform_job(event)
113
- execution = event.payload[:execution]
105
+ job = event.payload[:job]
114
106
  process_id = event.payload[:process_id]
115
107
  thread_name = event.payload[:thread_name]
116
108
 
117
109
  info(tags: [process_id, thread_name]) do
118
- "Executed GoodJob #{execution.id}"
110
+ "Executed GoodJob #{job.id}"
119
111
  end
120
112
  end
121
113
 
@@ -51,7 +51,7 @@ module GoodJob # :nodoc:
51
51
  # Send a message via Postgres NOTIFY
52
52
  # @param message [#to_json]
53
53
  def self.notify(message)
54
- connection = ::GoodJob::Execution.connection
54
+ connection = ::GoodJob::Job.connection
55
55
  connection.exec_query <<~SQL.squish
56
56
  NOTIFY #{CHANNEL}, #{connection.quote(message.to_json)}
57
57
  SQL
@@ -251,8 +251,8 @@ module GoodJob # :nodoc:
251
251
 
252
252
  def with_connection
253
253
  Rails.application.executor.wrap do
254
- self.connection = ::GoodJob::Execution.connection_pool.checkout.tap do |conn|
255
- ::GoodJob::Execution.connection_pool.remove(conn)
254
+ self.connection = ::GoodJob::Job.connection_pool.checkout.tap do |conn|
255
+ ::GoodJob::Job.connection_pool.remove(conn)
256
256
  end
257
257
  end
258
258
  connection.execute("SET application_name = #{connection.quote(self.class.name)}")
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GoodJob
4
4
  # GoodJob gem version.
5
- VERSION = '3.99.1'
5
+ VERSION = '4.0.0'
6
6
 
7
7
  # GoodJob version as Gem::Version object
8
8
  GEM_VERSION = Gem::Version.new(VERSION)
data/lib/good_job.rb CHANGED
@@ -58,7 +58,7 @@ module GoodJob
58
58
 
59
59
  # @!attribute [rw] active_record_parent_class
60
60
  # @!scope class
61
- # The ActiveRecord parent class inherited by +GoodJob::Execution+ (default: +ActiveRecord::Base+).
61
+ # The ActiveRecord parent class inherited by +GoodJob::Job+ (default: +ActiveRecord::Base+).
62
62
  # Use this when using multiple databases or other custom ActiveRecord configuration.
63
63
  # @return [ActiveRecord::Base]
64
64
  # @example Change the base class:
@@ -133,6 +133,7 @@ module GoodJob
133
133
  def self.configure_active_record(&block)
134
134
  self._active_record_configuration = block
135
135
  end
136
+
136
137
  mattr_accessor :_active_record_configuration, default: nil
137
138
 
138
139
  # Stop executing jobs.
@@ -208,7 +209,7 @@ module GoodJob
208
209
  include_discarded = GoodJob.configuration.cleanup_discarded_jobs?
209
210
 
210
211
  ActiveSupport::Notifications.instrument("cleanup_preserved_jobs.good_job", { older_than: older_than, timestamp: timestamp }) do |payload|
211
- deleted_executions_count = 0
212
+ deleted_jobs_count = 0
212
213
  deleted_batches_count = 0
213
214
  deleted_discrete_executions_count = 0
214
215
 
@@ -218,31 +219,27 @@ module GoodJob
218
219
  active_job_ids = jobs_query.pluck(:active_job_id)
219
220
  break if active_job_ids.empty?
220
221
 
221
- if GoodJob::Execution.discrete_support?
222
- deleted_discrete_executions = GoodJob::DiscreteExecution.where(active_job_id: active_job_ids).delete_all
223
- deleted_discrete_executions_count += deleted_discrete_executions
224
- end
222
+ deleted_discrete_executions = GoodJob::DiscreteExecution.where(active_job_id: active_job_ids).delete_all
223
+ deleted_discrete_executions_count += deleted_discrete_executions
225
224
 
226
- deleted_executions = GoodJob::Execution.where(active_job_id: active_job_ids).delete_all
227
- deleted_executions_count += deleted_executions
225
+ deleted_jobs = GoodJob::Job.where(active_job_id: active_job_ids).delete_all
226
+ deleted_jobs_count += deleted_jobs
228
227
  end
229
228
 
230
- if GoodJob::BatchRecord.migrated?
231
- batches_query = GoodJob::BatchRecord.finished_before(timestamp).limit(in_batches_of)
232
- batches_query = batches_query.succeeded unless include_discarded
233
- loop do
234
- deleted = batches_query.delete_all
235
- break if deleted.zero?
229
+ batches_query = GoodJob::BatchRecord.finished_before(timestamp).limit(in_batches_of)
230
+ batches_query = batches_query.succeeded unless include_discarded
231
+ loop do
232
+ deleted = batches_query.delete_all
233
+ break if deleted.zero?
236
234
 
237
- deleted_batches_count += deleted
238
- end
235
+ deleted_batches_count += deleted
239
236
  end
240
237
 
241
238
  payload[:destroyed_batches_count] = deleted_batches_count
242
239
  payload[:destroyed_discrete_executions_count] = deleted_discrete_executions_count
243
- payload[:destroyed_executions_count] = deleted_executions_count
240
+ payload[:destroyed_jobs_count] = deleted_jobs_count
244
241
 
245
- destroyed_records_count = deleted_batches_count + deleted_discrete_executions_count + deleted_executions_count
242
+ destroyed_records_count = deleted_batches_count + deleted_discrete_executions_count + deleted_jobs_count
246
243
  payload[:destroyed_records_count] = destroyed_records_count
247
244
 
248
245
  destroyed_records_count
@@ -272,7 +269,7 @@ module GoodJob
272
269
  # Tests whether GoodJob can be safely upgraded to v4
273
270
  # @return [Boolean]
274
271
  def self.v4_ready?
275
- GoodJob.migrated? && GoodJob::Job.discrete_support? && GoodJob::Job.where(finished_at: nil).where(is_discrete: [nil, false]).none?
272
+ GoodJob::Job.discrete_support? && GoodJob::Job.where(finished_at: nil).where(is_discrete: [nil, false]).none?
276
273
  end
277
274
 
278
275
  # Deprecator for providing deprecation warnings.
@@ -291,9 +288,7 @@ module GoodJob
291
288
  # For use in tests/CI to validate GoodJob is up-to-date.
292
289
  # @return [Boolean]
293
290
  def self.migrated?
294
- # Always update with the most recent migration check
295
- GoodJob::DiscreteExecution.reset_column_information
296
- GoodJob::DiscreteExecution.duration_interval_migrated?
291
+ true
297
292
  end
298
293
 
299
294
  ActiveSupport.run_load_hooks(:good_job, self)