good_job 3.15.13 → 3.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +56 -4
- data/README.md +27 -10
- data/app/controllers/good_job/application_controller.rb +16 -9
- data/app/controllers/good_job/batches_controller.rb +1 -0
- data/app/controllers/good_job/cron_entries_controller.rb +2 -1
- data/app/controllers/good_job/frontends_controller.rb +1 -0
- data/app/controllers/good_job/jobs_controller.rb +1 -0
- data/app/controllers/good_job/processes_controller.rb +1 -0
- data/app/filters/good_job/base_filter.rb +1 -0
- data/app/filters/good_job/batches_filter.rb +1 -0
- data/app/filters/good_job/jobs_filter.rb +1 -0
- data/app/helpers/good_job/application_helper.rb +1 -1
- data/app/models/concerns/good_job/error_events.rb +28 -0
- data/app/models/concerns/good_job/filterable.rb +1 -0
- data/app/models/{good_job → concerns/good_job}/lockable.rb +1 -0
- data/app/models/concerns/good_job/reportable.rb +1 -0
- data/app/models/good_job/active_record_parent_class.rb +9 -0
- data/app/models/good_job/base_execution.rb +10 -1
- data/app/models/good_job/base_record.rb +4 -1
- data/app/models/good_job/cron_entry.rb +1 -0
- data/app/models/good_job/discrete_execution.rb +9 -0
- data/app/models/good_job/execution.rb +41 -8
- data/app/models/good_job/execution_result.rb +17 -2
- data/app/models/good_job/i18n_config.rb +25 -0
- data/app/models/good_job/job.rb +4 -1
- data/app/models/good_job/process.rb +51 -18
- data/app/views/good_job/jobs/_executions.erb +1 -1
- data/app/views/good_job/jobs/_table.erb +17 -4
- data/app/views/good_job/processes/index.html.erb +6 -2
- data/app/views/good_job/shared/_navbar.erb +1 -1
- data/config/locales/de.yml +9 -1
- data/config/locales/en.yml +9 -1
- data/config/locales/es.yml +9 -1
- data/config/locales/fr.yml +9 -1
- data/config/locales/ja.yml +9 -1
- data/config/locales/nl.yml +9 -1
- data/config/locales/ru.yml +9 -1
- data/config/locales/tr.yml +227 -0
- data/config/locales/{ua.yml → uk.yml} +34 -2
- data/config/routes.rb +1 -0
- data/exe/good_job +1 -0
- data/lib/active_job/queue_adapters/good_job_adapter.rb +1 -0
- data/lib/generators/good_job/install_generator.rb +1 -0
- data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +5 -1
- data/lib/generators/good_job/templates/update/migrations/01_create_good_jobs.rb.erb +3 -1
- data/lib/generators/good_job/templates/update/migrations/02_create_good_job_settings.rb.erb +1 -0
- data/lib/generators/good_job/templates/update/migrations/03_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb.erb +1 -0
- data/lib/generators/good_job/templates/update/migrations/04_create_good_job_batches.rb.erb +1 -0
- data/lib/generators/good_job/templates/update/migrations/05_create_good_job_executions.rb.erb +1 -0
- data/lib/generators/good_job/templates/update/migrations/06_create_good_jobs_error_event.rb.erb +16 -0
- data/lib/generators/good_job/update_generator.rb +1 -0
- data/lib/good_job/active_job_extensions/batches.rb +1 -0
- data/lib/good_job/active_job_extensions/concurrency.rb +2 -1
- data/lib/good_job/active_job_extensions/interrupt_errors.rb +1 -0
- data/lib/good_job/active_job_extensions/notify_options.rb +1 -0
- data/lib/good_job/adapter.rb +3 -2
- data/lib/good_job/assignable_connection.rb +1 -0
- data/lib/good_job/bulk.rb +1 -0
- data/lib/good_job/capsule.rb +5 -4
- data/lib/good_job/cleanup_tracker.rb +2 -1
- data/lib/good_job/cli.rb +1 -0
- data/lib/good_job/configuration.rb +7 -0
- data/lib/good_job/cron_manager.rb +3 -3
- data/lib/good_job/current_thread.rb +8 -0
- data/lib/good_job/daemon.rb +1 -0
- data/lib/good_job/engine.rb +13 -0
- data/lib/good_job/interrupt_error.rb +1 -0
- data/lib/good_job/job_performer.rb +1 -0
- data/lib/good_job/log_subscriber.rb +1 -0
- data/lib/good_job/metrics.rb +57 -0
- data/lib/good_job/multi_scheduler.rb +1 -0
- data/lib/good_job/notifier/{process_registration.rb → process_heartbeat.rb} +10 -1
- data/lib/good_job/notifier.rb +18 -16
- data/lib/good_job/poller.rb +3 -3
- data/lib/good_job/scheduler.rb +30 -11
- data/lib/good_job/version.rb +2 -1
- data/lib/good_job.rb +15 -1
- metadata +11 -5
@@ -1,5 +1,5 @@
|
|
1
1
|
---
|
2
|
-
|
2
|
+
uk:
|
3
3
|
good_job:
|
4
4
|
actions:
|
5
5
|
destroy: Видалити
|
@@ -53,40 +53,64 @@ ua:
|
|
53
53
|
datetime:
|
54
54
|
distance_in_words:
|
55
55
|
about_x_hours:
|
56
|
+
few: близько %{count} годин
|
57
|
+
many: близько %{count} годин
|
56
58
|
one: близько 1 години
|
57
59
|
other: близько %{count} годин
|
58
60
|
about_x_months:
|
61
|
+
few: близько %{count} місяців
|
62
|
+
many: близько %{count} місяців
|
59
63
|
one: близько 1 місяця
|
60
64
|
other: близько %{count} місяців
|
61
65
|
about_x_years:
|
66
|
+
few: близько %{count} років
|
67
|
+
many: близько %{count} років
|
62
68
|
one: близько 1 року
|
63
69
|
other: близько %{count} років
|
64
70
|
almost_x_years:
|
71
|
+
few: майже %{count} роки
|
72
|
+
many: майже %{count} років
|
65
73
|
one: майже 1 рік
|
66
74
|
other: майже %{count} років
|
67
75
|
half_a_minute: півхвилини
|
68
76
|
less_than_x_minutes:
|
77
|
+
few: менше %{count} хвилин
|
78
|
+
many: менше %{count} хвилин
|
69
79
|
one: менше 1 хвилини
|
70
80
|
other: менше %{count} хвилин
|
71
81
|
less_than_x_seconds:
|
82
|
+
few: менше %{count} секунд
|
83
|
+
many: менше %{count} секунд
|
72
84
|
one: менше 1 секунди
|
73
85
|
other: менше %{count} секунд
|
74
86
|
over_x_years:
|
87
|
+
few: більше %{count} років
|
88
|
+
many: більше %{count} років
|
75
89
|
one: понад 1 рік
|
76
90
|
other: понад %{count} років
|
77
91
|
x_days:
|
92
|
+
few: "%{count} дні"
|
93
|
+
many: "%{count} днів"
|
78
94
|
one: 1 день
|
79
95
|
other: "%{count} днів"
|
80
96
|
x_minutes:
|
97
|
+
few: 1 хвилини
|
98
|
+
many: "%{count} хвилин"
|
81
99
|
one: 1 хвилина
|
82
100
|
other: "%{count} хвилин"
|
83
101
|
x_months:
|
102
|
+
few: "%{count} місяці"
|
103
|
+
many: "%{count} місяців"
|
84
104
|
one: 1 місяць
|
85
105
|
other: "%{count} місяців"
|
86
106
|
x_seconds:
|
107
|
+
few: "%{count} секунди"
|
108
|
+
many: "%{count} секунд"
|
87
109
|
one: 1 секунда
|
88
110
|
other: "%{count} секунд"
|
89
111
|
x_years:
|
112
|
+
few: "%{count} роки"
|
113
|
+
many: "%{count} років"
|
90
114
|
one: 1 рік
|
91
115
|
other: "%{count} років"
|
92
116
|
duration:
|
@@ -95,6 +119,13 @@ ua:
|
|
95
119
|
milliseconds: "%{ms}мс"
|
96
120
|
minutes: "%{min}хв %{sec}с"
|
97
121
|
seconds: "%{sec}с"
|
122
|
+
error_event:
|
123
|
+
discarded: Відкинуто
|
124
|
+
handled: Обробляється
|
125
|
+
interrupted: Перерваний
|
126
|
+
retried: Повторна спроба
|
127
|
+
retry_stopped: Повторну спробу зупинено
|
128
|
+
unhandled: Необроблений
|
98
129
|
helpers:
|
99
130
|
relative_time:
|
100
131
|
future: за %{time}
|
@@ -114,7 +145,6 @@ ua:
|
|
114
145
|
discard:
|
115
146
|
notice: Завдання було відхилено
|
116
147
|
executions:
|
117
|
-
error: Помилка
|
118
148
|
in_queue: у черзі
|
119
149
|
runtime: час виконання
|
120
150
|
title: Виконання
|
@@ -192,7 +222,9 @@ ua:
|
|
192
222
|
schedulers: Планувальники
|
193
223
|
started: Розпочато
|
194
224
|
title: Процеси
|
225
|
+
updated: Оновлено
|
195
226
|
shared:
|
227
|
+
error: Помилка
|
196
228
|
filter:
|
197
229
|
all: Всі
|
198
230
|
all_jobs: Усі роботи
|
data/config/routes.rb
CHANGED
data/exe/good_job
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
3
4
|
def change
|
4
|
-
|
5
|
+
# Uncomment for Postgres v12 or earlier to enable gen_random_uuid() support
|
6
|
+
# enable_extension 'pgcrypto'
|
5
7
|
|
6
8
|
create_table :good_jobs, id: :uuid do |t|
|
7
9
|
t.text :queue_name
|
@@ -26,6 +28,7 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
|
26
28
|
t.boolean :is_discrete
|
27
29
|
t.integer :executions_count
|
28
30
|
t.text :job_class
|
31
|
+
t.integer :error_event, limit: 2
|
29
32
|
end
|
30
33
|
|
31
34
|
create_table :good_job_batches, id: :uuid do |t|
|
@@ -52,6 +55,7 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
|
52
55
|
t.datetime :scheduled_at
|
53
56
|
t.datetime :finished_at
|
54
57
|
t.text :error
|
58
|
+
t.integer :error_event, limit: 2
|
55
59
|
end
|
56
60
|
|
57
61
|
create_table :good_job_processes, id: :uuid do |t|
|
@@ -1,7 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
3
4
|
def change
|
4
|
-
|
5
|
+
# Uncomment for Postgres v12 or earlier to enable gen_random_uuid() support
|
6
|
+
# enable_extension 'pgcrypto'
|
5
7
|
|
6
8
|
create_table :good_jobs, id: :uuid do |t|
|
7
9
|
t.text :queue_name
|
data/lib/generators/good_job/templates/update/migrations/06_create_good_jobs_error_event.rb.erb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateGoodJobsErrorEvent < ActiveRecord::Migration<%= migration_version %>
|
4
|
+
def change
|
5
|
+
reversible do |dir|
|
6
|
+
dir.up do
|
7
|
+
# Ensure this incremental update migration is idempotent
|
8
|
+
# with monolithic install migration.
|
9
|
+
return if connection.column_exists?(:good_jobs, :error_event)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
add_column :good_jobs, :error_event, :integer, limit: 2
|
14
|
+
add_column :good_job_executions, :error_event, :integer, limit: 2
|
15
|
+
end
|
16
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module GoodJob
|
3
4
|
module ActiveJobExtensions
|
4
5
|
module Concurrency
|
@@ -92,7 +93,7 @@ module GoodJob
|
|
92
93
|
key = self.class.good_job_concurrency_config[:key]
|
93
94
|
return if key.blank?
|
94
95
|
|
95
|
-
key = key.respond_to?(:call)
|
96
|
+
key = instance_exec(&key) if key.respond_to?(:call)
|
96
97
|
raise TypeError, "Concurrency key must be a String; was a #{key.class}" unless VALID_TYPES.any? { |type| key.is_a?(type) }
|
97
98
|
|
98
99
|
key
|
data/lib/good_job/adapter.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module GoodJob
|
3
4
|
#
|
4
5
|
# ActiveJob Adapter.
|
@@ -8,7 +9,7 @@ module GoodJob
|
|
8
9
|
# @!scope class
|
9
10
|
# List of all instantiated Adapters in the current process.
|
10
11
|
# @return [Array<GoodJob::Adapter>, nil]
|
11
|
-
cattr_reader :instances, default:
|
12
|
+
cattr_reader :instances, default: Concurrent::Array.new, instance_reader: false
|
12
13
|
|
13
14
|
# @param execution_mode [Symbol, nil] specifies how and where jobs should be executed. You can also set this with the environment variable +GOOD_JOB_EXECUTION_MODE+.
|
14
15
|
#
|
@@ -29,8 +30,8 @@ module GoodJob
|
|
29
30
|
GoodJob::Configuration.validate_execution_mode(@_execution_mode_override) if @_execution_mode_override
|
30
31
|
@capsule = _capsule
|
31
32
|
|
32
|
-
self.class.instances << self
|
33
33
|
start_async if GoodJob.async_ready?
|
34
|
+
self.class.instances << self
|
34
35
|
end
|
35
36
|
|
36
37
|
# Enqueues the ActiveJob job to be performed.
|
data/lib/good_job/bulk.rb
CHANGED
data/lib/good_job/capsule.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module GoodJob
|
3
4
|
# A GoodJob::Capsule contains the resources necessary to execute jobs, including
|
4
5
|
# a {GoodJob::Scheduler}, {GoodJob::Poller}, {GoodJob::Notifier}, and {GoodJob::CronManager}.
|
@@ -8,16 +9,16 @@ module GoodJob
|
|
8
9
|
# @!scope class
|
9
10
|
# List of all instantiated Capsules in the current process.
|
10
11
|
# @return [Array<GoodJob::Capsule>, nil]
|
11
|
-
cattr_reader :instances, default:
|
12
|
+
cattr_reader :instances, default: Concurrent::Array.new, instance_reader: false
|
12
13
|
|
13
14
|
# @param configuration [GoodJob::Configuration] Configuration to use for this capsule.
|
14
15
|
def initialize(configuration: GoodJob.configuration)
|
15
|
-
self.class.instances << self
|
16
16
|
@configuration = configuration
|
17
|
-
|
18
17
|
@startable = true
|
19
18
|
@running = false
|
20
19
|
@mutex = Mutex.new
|
20
|
+
|
21
|
+
self.class.instances << self
|
21
22
|
end
|
22
23
|
|
23
24
|
# Start the capsule once. After a shutdown, {#restart} must be used to start again.
|
@@ -49,7 +50,7 @@ module GoodJob
|
|
49
50
|
# * +nil+ will trigger a shutdown but not wait for it to complete.
|
50
51
|
# @return [void]
|
51
52
|
def shutdown(timeout: :default)
|
52
|
-
timeout =
|
53
|
+
timeout = @configuration.shutdown_timeout if timeout == :default
|
53
54
|
GoodJob._shutdown_all([@notifier, @poller, @scheduler, @cron_manager].compact, timeout: timeout)
|
54
55
|
@startable = false
|
55
56
|
@running = false
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module GoodJob # :nodoc:
|
3
4
|
# Tracks thresholds for cleaning up old jobs.
|
4
5
|
class CleanupTracker
|
@@ -17,7 +18,7 @@ module GoodJob # :nodoc:
|
|
17
18
|
end
|
18
19
|
|
19
20
|
# Increments job count.
|
20
|
-
# @return [
|
21
|
+
# @return [Integer]
|
21
22
|
def increment
|
22
23
|
self.job_count += 1
|
23
24
|
end
|
data/lib/good_job/cli.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module GoodJob
|
3
4
|
#
|
4
5
|
# +GoodJob::Configuration+ provides normalized configuration information to
|
@@ -28,6 +29,8 @@ module GoodJob
|
|
28
29
|
DEFAULT_ENABLE_CRON = false
|
29
30
|
# Default to enabling LISTEN/NOTIFY
|
30
31
|
DEFAULT_ENABLE_LISTEN_NOTIFY = true
|
32
|
+
# Default Dashboard I18n locale
|
33
|
+
DEFAULT_DASHBOARD_DEFAULT_LOCALE = :en
|
31
34
|
|
32
35
|
def self.validate_execution_mode(execution_mode)
|
33
36
|
raise ArgumentError, "GoodJob execution mode must be one of #{EXECUTION_MODES.join(', ')}. It was '#{execution_mode}' which is not valid." unless execution_mode.in?(EXECUTION_MODES)
|
@@ -345,6 +348,10 @@ module GoodJob
|
|
345
348
|
rails_config[:smaller_number_is_higher_priority]
|
346
349
|
end
|
347
350
|
|
351
|
+
def dashboard_default_locale
|
352
|
+
rails_config[:dashboard_default_locale] || DEFAULT_DASHBOARD_DEFAULT_LOCALE
|
353
|
+
end
|
354
|
+
|
348
355
|
private
|
349
356
|
|
350
357
|
def rails_config
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "concurrent/hash"
|
3
4
|
require "concurrent/scheduled_task"
|
4
5
|
require "fugit"
|
@@ -12,7 +13,7 @@ module GoodJob # :nodoc:
|
|
12
13
|
# @!scope class
|
13
14
|
# List of all instantiated CronManagers in the current process.
|
14
15
|
# @return [Array<GoodJob::CronManager>, nil]
|
15
|
-
cattr_reader :instances, default:
|
16
|
+
cattr_reader :instances, default: Concurrent::Array.new, instance_reader: false
|
16
17
|
|
17
18
|
# Task observer for cron task
|
18
19
|
# @param time [Time]
|
@@ -35,9 +36,8 @@ module GoodJob # :nodoc:
|
|
35
36
|
@cron_entries = cron_entries
|
36
37
|
@tasks = Concurrent::Hash.new
|
37
38
|
|
38
|
-
self.class.instances << self
|
39
|
-
|
40
39
|
start if start_on_initialize
|
40
|
+
self.class.instances << self
|
41
41
|
end
|
42
42
|
|
43
43
|
# Schedule tasks that will enqueue jobs based on their schedule
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'active_support/core_ext/module/attribute_accessors_per_thread'
|
3
4
|
|
4
5
|
module GoodJob
|
@@ -11,6 +12,7 @@ module GoodJob
|
|
11
12
|
cron_key
|
12
13
|
error_on_discard
|
13
14
|
error_on_retry
|
15
|
+
error_on_retry_stopped
|
14
16
|
execution
|
15
17
|
execution_interrupted
|
16
18
|
execution_retried
|
@@ -40,6 +42,12 @@ module GoodJob
|
|
40
42
|
# @return [Exception, nil]
|
41
43
|
thread_mattr_accessor :error_on_retry
|
42
44
|
|
45
|
+
# @!attribute [rw] error_on_retry_stopped
|
46
|
+
# @!scope class
|
47
|
+
# Error captured by retry_stopped
|
48
|
+
# @return [Exception, nil]
|
49
|
+
thread_mattr_accessor :error_on_retry_stopped
|
50
|
+
|
43
51
|
# @!attribute [rw] executions
|
44
52
|
# @!scope class
|
45
53
|
# Execution
|
data/lib/good_job/daemon.rb
CHANGED
data/lib/good_job/engine.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module GoodJob
|
3
4
|
# Ruby on Rails integration.
|
4
5
|
class Engine < ::Rails::Engine
|
@@ -19,6 +20,10 @@ module GoodJob
|
|
19
20
|
GoodJob::CurrentThread.error_on_retry = event.payload[:error]
|
20
21
|
end
|
21
22
|
|
23
|
+
ActiveSupport::Notifications.subscribe "retry_stopped.active_job" do |event|
|
24
|
+
GoodJob::CurrentThread.error_on_retry_stopped = event.payload[:error]
|
25
|
+
end
|
26
|
+
|
22
27
|
ActiveSupport::Notifications.subscribe "discard.active_job" do |event|
|
23
28
|
GoodJob::CurrentThread.error_on_discard = event.payload[:error]
|
24
29
|
end
|
@@ -35,6 +40,14 @@ module GoodJob
|
|
35
40
|
end
|
36
41
|
end
|
37
42
|
|
43
|
+
initializer 'good_job.active_record' do
|
44
|
+
config.to_prepare do
|
45
|
+
ActiveSupport.on_load :good_job_base_record, run_once: true do
|
46
|
+
GoodJob::BaseRecord.class_eval(&GoodJob._active_record_configuration) if GoodJob._active_record_configuration
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
38
51
|
initializer "good_job.start_async" do
|
39
52
|
# This hooks into the hookable places during Rails boot, which is unfortunately not Rails.application.initialized?
|
40
53
|
# If an Adapter is initialized during boot, we want to want to start async executors once the framework dependencies have loaded.
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GoodJob # :nodoc:
|
4
|
+
# Metrics for the scheduler.
|
5
|
+
class Metrics
|
6
|
+
def initialize
|
7
|
+
@empty_executions = Concurrent::AtomicFixnum.new
|
8
|
+
@errored_executions = Concurrent::AtomicFixnum.new
|
9
|
+
@succeeded_executions = Concurrent::AtomicFixnum.new
|
10
|
+
@unexecutable_executions = Concurrent::AtomicFixnum.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Increments number of empty queried executions.
|
14
|
+
# @return [Integer]
|
15
|
+
def increment_empty_executions
|
16
|
+
@empty_executions.increment
|
17
|
+
end
|
18
|
+
|
19
|
+
# Increments number of failed executions.
|
20
|
+
# @return [Integer]
|
21
|
+
def increment_errored_executions
|
22
|
+
@errored_executions.increment
|
23
|
+
end
|
24
|
+
|
25
|
+
# Increments number of succeeded executions.
|
26
|
+
# @return [Integer]
|
27
|
+
def increment_succeeded_executions
|
28
|
+
@succeeded_executions.increment
|
29
|
+
end
|
30
|
+
|
31
|
+
# Increments number of unlocked executions.
|
32
|
+
# @return [Integer]
|
33
|
+
def increment_unexecutable_executions
|
34
|
+
@unexecutable_executions.increment
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_h
|
38
|
+
{
|
39
|
+
empty_executions_count: @empty_executions.value,
|
40
|
+
errored_executions_count: @errored_executions.value,
|
41
|
+
succeeded_executions_count: @succeeded_executions.value,
|
42
|
+
unexecutable_executions_count: @unexecutable_executions.value,
|
43
|
+
}.tap do |values|
|
44
|
+
values[:total_executions_count] = values.values.sum
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Reset counters.
|
49
|
+
# @return [void]
|
50
|
+
def reset
|
51
|
+
@empty_executions.value = 0
|
52
|
+
@errored_executions.value = 0
|
53
|
+
@succeeded_executions.value = 0
|
54
|
+
@unexecutable_executions.value = 0
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -3,11 +3,12 @@
|
|
3
3
|
module GoodJob # :nodoc:
|
4
4
|
class Notifier # :nodoc:
|
5
5
|
# Extends the Notifier to register the process in the database.
|
6
|
-
module
|
6
|
+
module ProcessHeartbeat
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
included do
|
10
10
|
set_callback :listen, :after, :register_process
|
11
|
+
set_callback :tick, :before, :refresh_process
|
11
12
|
set_callback :unlisten, :after, :deregister_process
|
12
13
|
end
|
13
14
|
|
@@ -19,6 +20,14 @@ module GoodJob # :nodoc:
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
def refresh_process
|
24
|
+
GoodJob::Process.with_connection(connection) do
|
25
|
+
Process.logger.silence do
|
26
|
+
@process&.refresh_if_stale(cleanup: true)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
22
31
|
# Deregisters the current process.
|
23
32
|
def deregister_process
|
24
33
|
GoodJob::Process.with_connection(connection) do
|
data/lib/good_job/notifier.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'active_support/core_ext/module/attribute_accessors_per_thread'
|
3
4
|
require 'concurrent/atomic/atomic_boolean'
|
4
|
-
require "good_job/notifier/
|
5
|
+
require "good_job/notifier/process_heartbeat"
|
5
6
|
|
6
7
|
module GoodJob # :nodoc:
|
7
8
|
#
|
@@ -13,9 +14,9 @@ module GoodJob # :nodoc:
|
|
13
14
|
#
|
14
15
|
class Notifier
|
15
16
|
include ActiveSupport::Callbacks
|
16
|
-
define_callbacks :listen, :unlisten
|
17
|
+
define_callbacks :listen, :tick, :unlisten
|
17
18
|
|
18
|
-
include
|
19
|
+
include ProcessHeartbeat
|
19
20
|
|
20
21
|
# Default Postgres channel for LISTEN/NOTIFY
|
21
22
|
CHANNEL = 'good_job'
|
@@ -46,7 +47,7 @@ module GoodJob # :nodoc:
|
|
46
47
|
# @!scope class
|
47
48
|
# List of all instantiated Notifiers in the current process.
|
48
49
|
# @return [Array<GoodJob::Notifier>, nil]
|
49
|
-
cattr_reader :instances, default:
|
50
|
+
cattr_reader :instances, default: Concurrent::Array.new, instance_reader: false
|
50
51
|
|
51
52
|
# @!attribute [rw] connection
|
52
53
|
# @!scope class
|
@@ -77,10 +78,9 @@ module GoodJob # :nodoc:
|
|
77
78
|
@connection_errors_reported = Concurrent::AtomicBoolean.new(false)
|
78
79
|
@enable_listening = enable_listening
|
79
80
|
|
80
|
-
self.class.instances << self
|
81
|
-
|
82
81
|
create_executor
|
83
82
|
listen
|
83
|
+
self.class.instances << self
|
84
84
|
end
|
85
85
|
|
86
86
|
# Tests whether the notifier is active and has acquired a dedicated database connection.
|
@@ -189,18 +189,20 @@ module GoodJob # :nodoc:
|
|
189
189
|
end
|
190
190
|
|
191
191
|
while thr_executor.running?
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
192
|
+
run_callbacks :tick do
|
193
|
+
wait_for_notify do |channel, payload|
|
194
|
+
next unless channel == CHANNEL
|
195
|
+
|
196
|
+
ActiveSupport::Notifications.instrument("notifier_notified.good_job", { payload: payload })
|
197
|
+
parsed_payload = JSON.parse(payload, symbolize_names: true)
|
198
|
+
thr_recipients.each do |recipient|
|
199
|
+
target, method_name = recipient.is_a?(Array) ? recipient : [recipient, :call]
|
200
|
+
target.send(method_name, parsed_payload)
|
201
|
+
end
|
200
202
|
end
|
201
|
-
end
|
202
203
|
|
203
|
-
|
204
|
+
reset_connection_errors
|
205
|
+
end
|
204
206
|
end
|
205
207
|
end
|
206
208
|
ensure
|