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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +56 -4
  3. data/README.md +27 -10
  4. data/app/controllers/good_job/application_controller.rb +16 -9
  5. data/app/controllers/good_job/batches_controller.rb +1 -0
  6. data/app/controllers/good_job/cron_entries_controller.rb +2 -1
  7. data/app/controllers/good_job/frontends_controller.rb +1 -0
  8. data/app/controllers/good_job/jobs_controller.rb +1 -0
  9. data/app/controllers/good_job/processes_controller.rb +1 -0
  10. data/app/filters/good_job/base_filter.rb +1 -0
  11. data/app/filters/good_job/batches_filter.rb +1 -0
  12. data/app/filters/good_job/jobs_filter.rb +1 -0
  13. data/app/helpers/good_job/application_helper.rb +1 -1
  14. data/app/models/concerns/good_job/error_events.rb +28 -0
  15. data/app/models/concerns/good_job/filterable.rb +1 -0
  16. data/app/models/{good_job → concerns/good_job}/lockable.rb +1 -0
  17. data/app/models/concerns/good_job/reportable.rb +1 -0
  18. data/app/models/good_job/active_record_parent_class.rb +9 -0
  19. data/app/models/good_job/base_execution.rb +10 -1
  20. data/app/models/good_job/base_record.rb +4 -1
  21. data/app/models/good_job/cron_entry.rb +1 -0
  22. data/app/models/good_job/discrete_execution.rb +9 -0
  23. data/app/models/good_job/execution.rb +41 -8
  24. data/app/models/good_job/execution_result.rb +17 -2
  25. data/app/models/good_job/i18n_config.rb +25 -0
  26. data/app/models/good_job/job.rb +4 -1
  27. data/app/models/good_job/process.rb +51 -18
  28. data/app/views/good_job/jobs/_executions.erb +1 -1
  29. data/app/views/good_job/jobs/_table.erb +17 -4
  30. data/app/views/good_job/processes/index.html.erb +6 -2
  31. data/app/views/good_job/shared/_navbar.erb +1 -1
  32. data/config/locales/de.yml +9 -1
  33. data/config/locales/en.yml +9 -1
  34. data/config/locales/es.yml +9 -1
  35. data/config/locales/fr.yml +9 -1
  36. data/config/locales/ja.yml +9 -1
  37. data/config/locales/nl.yml +9 -1
  38. data/config/locales/ru.yml +9 -1
  39. data/config/locales/tr.yml +227 -0
  40. data/config/locales/{ua.yml → uk.yml} +34 -2
  41. data/config/routes.rb +1 -0
  42. data/exe/good_job +1 -0
  43. data/lib/active_job/queue_adapters/good_job_adapter.rb +1 -0
  44. data/lib/generators/good_job/install_generator.rb +1 -0
  45. data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +5 -1
  46. data/lib/generators/good_job/templates/update/migrations/01_create_good_jobs.rb.erb +3 -1
  47. data/lib/generators/good_job/templates/update/migrations/02_create_good_job_settings.rb.erb +1 -0
  48. data/lib/generators/good_job/templates/update/migrations/03_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb.erb +1 -0
  49. data/lib/generators/good_job/templates/update/migrations/04_create_good_job_batches.rb.erb +1 -0
  50. data/lib/generators/good_job/templates/update/migrations/05_create_good_job_executions.rb.erb +1 -0
  51. data/lib/generators/good_job/templates/update/migrations/06_create_good_jobs_error_event.rb.erb +16 -0
  52. data/lib/generators/good_job/update_generator.rb +1 -0
  53. data/lib/good_job/active_job_extensions/batches.rb +1 -0
  54. data/lib/good_job/active_job_extensions/concurrency.rb +2 -1
  55. data/lib/good_job/active_job_extensions/interrupt_errors.rb +1 -0
  56. data/lib/good_job/active_job_extensions/notify_options.rb +1 -0
  57. data/lib/good_job/adapter.rb +3 -2
  58. data/lib/good_job/assignable_connection.rb +1 -0
  59. data/lib/good_job/bulk.rb +1 -0
  60. data/lib/good_job/capsule.rb +5 -4
  61. data/lib/good_job/cleanup_tracker.rb +2 -1
  62. data/lib/good_job/cli.rb +1 -0
  63. data/lib/good_job/configuration.rb +7 -0
  64. data/lib/good_job/cron_manager.rb +3 -3
  65. data/lib/good_job/current_thread.rb +8 -0
  66. data/lib/good_job/daemon.rb +1 -0
  67. data/lib/good_job/engine.rb +13 -0
  68. data/lib/good_job/interrupt_error.rb +1 -0
  69. data/lib/good_job/job_performer.rb +1 -0
  70. data/lib/good_job/log_subscriber.rb +1 -0
  71. data/lib/good_job/metrics.rb +57 -0
  72. data/lib/good_job/multi_scheduler.rb +1 -0
  73. data/lib/good_job/notifier/{process_registration.rb → process_heartbeat.rb} +10 -1
  74. data/lib/good_job/notifier.rb +18 -16
  75. data/lib/good_job/poller.rb +3 -3
  76. data/lib/good_job/scheduler.rb +30 -11
  77. data/lib/good_job/version.rb +2 -1
  78. data/lib/good_job.rb +15 -1
  79. metadata +11 -5
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'concurrent/atomic/atomic_boolean'
3
4
 
4
5
  module GoodJob # :nodoc:
@@ -17,7 +18,7 @@ module GoodJob # :nodoc:
17
18
  # @!scope class
18
19
  # List of all instantiated Pollers in the current process.
19
20
  # @return [Array<GoodJob::Poller>, nil]
20
- cattr_reader :instances, default: [], instance_reader: false
21
+ cattr_reader :instances, default: Concurrent::Array.new, instance_reader: false
21
22
 
22
23
  # Creates GoodJob::Poller from a GoodJob::Configuration instance.
23
24
  # @param configuration [GoodJob::Configuration]
@@ -38,9 +39,8 @@ module GoodJob # :nodoc:
38
39
  @timer_options = DEFAULT_TIMER_OPTIONS.dup
39
40
  @timer_options[:execution_interval] = poll_interval if poll_interval.present?
40
41
 
41
- self.class.instances << self
42
-
43
42
  create_timer
43
+ self.class.instances << self
44
44
  end
45
45
 
46
46
  # Tests whether the timer is running.
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "concurrent/executor/thread_pool_executor"
3
4
  require "concurrent/executor/timer_set"
4
5
  require "concurrent/scheduled_task"
5
6
  require "concurrent/utility/processor_counter"
7
+ require 'good_job/metrics'
6
8
 
7
9
  module GoodJob # :nodoc:
8
10
  #
@@ -32,7 +34,7 @@ module GoodJob # :nodoc:
32
34
  # @!scope class
33
35
  # List of all instantiated Schedulers in the current process.
34
36
  # @return [Array<GoodJob::Scheduler>, nil]
35
- cattr_reader :instances, default: [], instance_reader: false
37
+ cattr_reader :instances, default: Concurrent::Array.new, instance_reader: false
36
38
 
37
39
  # Creates GoodJob::Scheduler(s) and Performers from a GoodJob::Configuration instance.
38
40
  # @param configuration [GoodJob::Configuration]
@@ -74,8 +76,6 @@ module GoodJob # :nodoc:
74
76
  def initialize(performer, max_threads: nil, max_cache: nil, warm_cache_on_initialize: false, cleanup_interval_seconds: nil, cleanup_interval_jobs: nil)
75
77
  raise ArgumentError, "Performer argument must implement #next" unless performer.respond_to?(:next)
76
78
 
77
- self.class.instances << self
78
-
79
79
  @performer = performer
80
80
 
81
81
  @max_cache = max_cache || 0
@@ -88,8 +88,12 @@ module GoodJob # :nodoc:
88
88
  @executor_options[:name] = name
89
89
 
90
90
  @cleanup_tracker = CleanupTracker.new(cleanup_interval_seconds: cleanup_interval_seconds, cleanup_interval_jobs: cleanup_interval_jobs)
91
+ @metrics = ::GoodJob::Metrics.new
92
+ @executor_options[:name] = name
93
+
91
94
  create_executor
92
95
  warm_cache if warm_cache_on_initialize
96
+ self.class.instances << self
93
97
  end
94
98
 
95
99
  # Tests whether the scheduler is running.
@@ -139,6 +143,7 @@ module GoodJob # :nodoc:
139
143
 
140
144
  instrument("scheduler_restart_pools") do
141
145
  shutdown(timeout: timeout)
146
+ @metrics.reset
142
147
  create_executor
143
148
  warm_cache
144
149
  end
@@ -197,8 +202,20 @@ module GoodJob # :nodoc:
197
202
  # @!visibility private
198
203
  # @return [void]
199
204
  def task_observer(time, output, thread_error)
200
- error = thread_error || (output.is_a?(GoodJob::ExecutionResult) ? output.unhandled_error : nil)
201
- GoodJob._on_thread_error(error) if error
205
+ result = output.is_a?(GoodJob::ExecutionResult) ? output : nil
206
+
207
+ unhandled_error = thread_error || result&.unhandled_error
208
+ GoodJob._on_thread_error(unhandled_error) if unhandled_error
209
+
210
+ if unhandled_error || result&.handled_error
211
+ @metrics.increment_errored_executions
212
+ elsif result&.unexecutable
213
+ @metrics.increment_unexecutable_executions
214
+ elsif result
215
+ @metrics.increment_succeeded_executions
216
+ else
217
+ @metrics.increment_empty_executions
218
+ end
202
219
 
203
220
  instrument("finished_job_task", { result: output, error: thread_error, time: time })
204
221
  return unless output
@@ -214,15 +231,17 @@ module GoodJob # :nodoc:
214
231
  # Information about the Scheduler
215
232
  # @return [Hash]
216
233
  def stats
234
+ available_threads = executor.ready_worker_count
217
235
  {
218
- name: performer.name,
236
+ name: name,
237
+ queues: performer.name,
219
238
  max_threads: @executor_options[:max_threads],
220
- active_threads: @executor_options[:max_threads] - executor.ready_worker_count,
221
- available_threads: executor.ready_worker_count,
239
+ active_threads: @executor_options[:max_threads] - available_threads,
240
+ available_threads: available_threads,
222
241
  max_cache: @max_cache,
223
242
  active_cache: cache_count,
224
243
  available_cache: remaining_cache_count,
225
- }
244
+ }.merge!(@metrics.to_h)
226
245
  end
227
246
 
228
247
  # Preload existing runnable and future-scheduled jobs
@@ -316,7 +335,7 @@ module GoodJob # :nodoc:
316
335
 
317
336
  # Custom sub-class of +Concurrent::ThreadPoolExecutor+ to add additional worker status.
318
337
  # @private
319
- class ThreadPoolExecutor < Concurrent::ThreadPoolExecutor
338
+ class ThreadPoolExecutor < ::Concurrent::ThreadPoolExecutor
320
339
  # Number of inactive threads available to execute tasks.
321
340
  # https://github.com/ruby-concurrency/concurrent-ruby/issues/684#issuecomment-427594437
322
341
  # @return [Integer]
@@ -335,7 +354,7 @@ module GoodJob # :nodoc:
335
354
 
336
355
  # Custom sub-class of +Concurrent::TimerSet+ for additional behavior.
337
356
  # @private
338
- class TimerSet < Concurrent::TimerSet
357
+ class TimerSet < ::Concurrent::TimerSet
339
358
  # Number of scheduled jobs in the queue
340
359
  # @return [Integer]
341
360
  def length
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module GoodJob
3
4
  # GoodJob gem version.
4
- VERSION = '3.15.13'
5
+ VERSION = '3.16.0'
5
6
 
6
7
  # GoodJob version as Gem::Version object
7
8
  GEM_VERSION = Gem::Version.new(VERSION)
data/lib/good_job.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "active_job"
3
4
  require "active_job/queue_adapters"
4
5
 
@@ -46,7 +47,7 @@ module GoodJob
46
47
  # @return [ActiveRecord::Base]
47
48
  # @example Change the base class:
48
49
  # GoodJob.active_record_parent_class = "CustomApplicationRecord"
49
- mattr_accessor :active_record_parent_class, default: "ActiveRecord::Base"
50
+ mattr_accessor :active_record_parent_class, default: nil
50
51
 
51
52
  # @!attribute [rw] logger
52
53
  # @!scope class
@@ -105,6 +106,19 @@ module GoodJob
105
106
  on_thread_error.call(exception) if on_thread_error.respond_to?(:call)
106
107
  end
107
108
 
109
+ # Custom Active Record configuration that is class_eval'ed into +GoodJob::BaseRecord+
110
+ # @param block Custom Active Record configuration
111
+ # @retyrn [void]
112
+ #
113
+ # @example
114
+ # GoodJob.configure_active_record do
115
+ # connects_to database: :special_database
116
+ # end
117
+ def self.configure_active_record(&block)
118
+ self._active_record_configuration = block
119
+ end
120
+ mattr_accessor :_active_record_configuration, default: nil
121
+
108
122
  # Stop executing jobs.
109
123
  # GoodJob does its work in pools of background threads.
110
124
  # When forking processes you should shut down these background threads before forking, and restart them after forking.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: good_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.15.13
4
+ version: 3.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-06-14 00:00:00.000000000 Z
11
+ date: 2023-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -343,8 +343,11 @@ files:
343
343
  - app/frontend/good_job/vendor/rails_ujs.js
344
344
  - app/frontend/good_job/vendor/stimulus.js
345
345
  - app/helpers/good_job/application_helper.rb
346
+ - app/models/concerns/good_job/error_events.rb
346
347
  - app/models/concerns/good_job/filterable.rb
348
+ - app/models/concerns/good_job/lockable.rb
347
349
  - app/models/concerns/good_job/reportable.rb
350
+ - app/models/good_job/active_record_parent_class.rb
348
351
  - app/models/good_job/base_execution.rb
349
352
  - app/models/good_job/base_record.rb
350
353
  - app/models/good_job/batch.rb
@@ -353,8 +356,8 @@ files:
353
356
  - app/models/good_job/discrete_execution.rb
354
357
  - app/models/good_job/execution.rb
355
358
  - app/models/good_job/execution_result.rb
359
+ - app/models/good_job/i18n_config.rb
356
360
  - app/models/good_job/job.rb
357
- - app/models/good_job/lockable.rb
358
361
  - app/models/good_job/process.rb
359
362
  - app/models/good_job/setting.rb
360
363
  - app/views/good_job/batches/_jobs.erb
@@ -393,7 +396,8 @@ files:
393
396
  - config/locales/ja.yml
394
397
  - config/locales/nl.yml
395
398
  - config/locales/ru.yml
396
- - config/locales/ua.yml
399
+ - config/locales/tr.yml
400
+ - config/locales/uk.yml
397
401
  - config/routes.rb
398
402
  - exe/good_job
399
403
  - lib/active_job/queue_adapters/good_job_adapter.rb
@@ -404,6 +408,7 @@ files:
404
408
  - lib/generators/good_job/templates/update/migrations/03_create_index_good_jobs_jobs_on_priority_created_at_when_unfinished.rb.erb
405
409
  - lib/generators/good_job/templates/update/migrations/04_create_good_job_batches.rb.erb
406
410
  - lib/generators/good_job/templates/update/migrations/05_create_good_job_executions.rb.erb
411
+ - lib/generators/good_job/templates/update/migrations/06_create_good_jobs_error_event.rb.erb
407
412
  - lib/generators/good_job/update_generator.rb
408
413
  - lib/good_job.rb
409
414
  - lib/good_job/active_job_extensions/batches.rb
@@ -425,9 +430,10 @@ files:
425
430
  - lib/good_job/interrupt_error.rb
426
431
  - lib/good_job/job_performer.rb
427
432
  - lib/good_job/log_subscriber.rb
433
+ - lib/good_job/metrics.rb
428
434
  - lib/good_job/multi_scheduler.rb
429
435
  - lib/good_job/notifier.rb
430
- - lib/good_job/notifier/process_registration.rb
436
+ - lib/good_job/notifier/process_heartbeat.rb
431
437
  - lib/good_job/poller.rb
432
438
  - lib/good_job/probe_server.rb
433
439
  - lib/good_job/scheduler.rb