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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +0 -61
- data/app/charts/good_job/scheduled_by_queue_chart.rb +2 -2
- data/app/controllers/good_job/cron_entries_controller.rb +0 -8
- data/app/controllers/good_job/metrics_controller.rb +1 -1
- data/app/controllers/good_job/performances_controller.rb +5 -9
- data/app/models/concerns/good_job/filterable.rb +1 -1
- data/app/models/good_job/base_execution.rb +104 -201
- data/app/models/good_job/cron_entry.rb +0 -2
- data/app/models/good_job/discrete_execution.rb +1 -31
- data/app/models/good_job/execution.rb +3 -7
- data/app/models/good_job/job.rb +37 -116
- data/app/models/good_job/process.rb +7 -20
- data/app/views/good_job/batches/index.html.erb +11 -15
- data/app/views/good_job/jobs/_executions.erb +1 -1
- data/app/views/good_job/jobs/_table.erb +1 -1
- data/app/views/good_job/jobs/show.html.erb +1 -8
- data/app/views/good_job/performances/show.html.erb +33 -40
- data/config/locales/de.yml +1 -4
- data/config/locales/en.yml +1 -4
- data/config/locales/es.yml +1 -4
- data/config/locales/fr.yml +1 -4
- data/config/locales/it.yml +1 -4
- data/config/locales/ja.yml +1 -4
- data/config/locales/ko.yml +1 -4
- data/config/locales/nl.yml +1 -4
- data/config/locales/pt-BR.yml +1 -4
- data/config/locales/ru.yml +1 -4
- data/config/locales/tr.yml +1 -4
- data/config/locales/uk.yml +1 -4
- data/lib/generators/good_job/templates/update/migrations/01_create_good_jobs.rb.erb +65 -3
- data/lib/good_job/active_job_extensions/batches.rb +1 -1
- data/lib/good_job/active_job_extensions/concurrency.rb +10 -10
- data/lib/good_job/adapter.rb +13 -24
- data/lib/good_job/current_thread.rb +6 -6
- data/lib/good_job/job_performer.rb +2 -2
- data/lib/good_job/log_subscriber.rb +2 -10
- data/lib/good_job/notifier.rb +3 -3
- data/lib/good_job/version.rb +1 -1
- data/lib/good_job.rb +17 -22
- metadata +16 -30
- data/lib/generators/good_job/templates/update/migrations/02_create_good_job_settings.rb.erb +0 -20
- data/lib/generators/good_job/templates/update/migrations/03_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb.erb +0 -19
- data/lib/generators/good_job/templates/update/migrations/04_create_good_job_batches.rb.erb +0 -35
- data/lib/generators/good_job/templates/update/migrations/05_create_good_job_executions.rb.erb +0 -33
- data/lib/generators/good_job/templates/update/migrations/06_create_good_jobs_error_event.rb.erb +0 -16
- data/lib/generators/good_job/templates/update/migrations/07_recreate_good_job_cron_indexes_with_conditional.rb.erb +0 -45
- data/lib/generators/good_job/templates/update/migrations/08_create_good_job_labels.rb.erb +0 -15
- data/lib/generators/good_job/templates/update/migrations/09_create_good_job_labels_index.rb.erb +0 -22
- data/lib/generators/good_job/templates/update/migrations/10_remove_good_job_active_id_index.rb.erb +0 -21
- data/lib/generators/good_job/templates/update/migrations/11_create_index_good_job_jobs_for_candidate_lookup.rb.erb +0 -19
- data/lib/generators/good_job/templates/update/migrations/12_create_good_job_execution_error_backtrace.rb.erb +0 -15
- data/lib/generators/good_job/templates/update/migrations/13_create_good_job_process_lock_ids.rb.erb +0 -18
- data/lib/generators/good_job/templates/update/migrations/14_create_good_job_process_lock_indexes.rb.erb +0 -38
- data/lib/generators/good_job/templates/update/migrations/15_create_good_job_execution_duration.rb.erb +0 -15
data/config/locales/it.yml
CHANGED
@@ -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.
|
data/config/locales/ja.yml
CHANGED
@@ -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 移行を実行してください。
|
data/config/locales/ko.yml
CHANGED
@@ -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 마이그레이션을 실행하세요.
|
data/config/locales/nl.yml
CHANGED
@@ -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.
|
data/config/locales/pt-BR.yml
CHANGED
@@ -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.
|
data/config/locales/ru.yml
CHANGED
@@ -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.
|
data/config/locales/tr.yml
CHANGED
@@ -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.
|
data/config/locales/uk.yml
CHANGED
@@ -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: :
|
36
|
-
add_index :good_jobs, [:cron_key, :cron_at],
|
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.
|
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
|
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.
|
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::
|
83
|
+
GoodJob::Job.advisory_lock_key(key, function: "pg_advisory_lock") do
|
84
84
|
if limit
|
85
|
-
allowed_active_job_ids = GoodJob::
|
86
|
-
|
87
|
-
|
88
|
-
|
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::
|
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::
|
178
|
+
GoodJob::Job.where(concurrency_key: key).unfinished.advisory_unlocked.count
|
179
179
|
else
|
180
|
-
GoodJob::
|
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
|
data/lib/good_job/adapter.rb
CHANGED
@@ -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::
|
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::
|
62
|
-
if
|
63
|
-
|
64
|
-
|
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::
|
74
|
-
execution_attributes = executions.map
|
75
|
-
|
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::
|
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.
|
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::
|
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::
|
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::
|
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
|
-
|
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]
|
52
|
+
# @!attribute [rw] jobs
|
53
53
|
# @!scope class
|
54
54
|
# Execution
|
55
|
-
# @return [GoodJob::
|
56
|
-
thread_mattr_accessor :
|
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::
|
93
|
+
# @return [String] UUID of the currently executing GoodJob::Job
|
94
94
|
def self.active_job_id
|
95
|
-
|
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::
|
111
|
+
@_job_query ||= GoodJob::Job.queue_string(queue_string)
|
112
112
|
end
|
113
113
|
|
114
114
|
def parsed_queues
|
115
|
-
@_parsed_queues ||= GoodJob::
|
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
|
-
|
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 #{
|
110
|
+
"Executed GoodJob #{job.id}"
|
119
111
|
end
|
120
112
|
end
|
121
113
|
|
data/lib/good_job/notifier.rb
CHANGED
@@ -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::
|
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::
|
255
|
-
::GoodJob::
|
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)}")
|
data/lib/good_job/version.rb
CHANGED
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::
|
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
|
-
|
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
|
-
|
222
|
-
|
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
|
-
|
227
|
-
|
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
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
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
|
-
|
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[:
|
240
|
+
payload[:destroyed_jobs_count] = deleted_jobs_count
|
244
241
|
|
245
|
-
destroyed_records_count = deleted_batches_count + deleted_discrete_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
|
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
|
-
|
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)
|