good_job 3.15.13 → 3.16.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 +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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20bb64485159969378a5abf5d960de13a3f27df63846f85cda6e4ef410c9af23
|
|
4
|
+
data.tar.gz: de0d39b68577c973ca4a4c9d9bccd8bda29bad7e6ca5a936112db7c8df6b038b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fa9474d0ee2ff9e8e47aa5e3cc31d6cd1924c7d00276a9da2bc4611b970ea80d68a0bc79c9da7f4266c85e0bedfc491860dabff4d4e1088d485a11a21a895f5
|
|
7
|
+
data.tar.gz: eb6a2ea5cdacd25fd930aab7eba6b498ffb5998fa82c78e552f7acaebf59f6f6cd950fb6488e4c317b461ff8931df5250820cdeb46d40a4047a1e8c24495756b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v3.16.0](https://github.com/bensheldon/good_job/tree/v3.16.0) (2023-07-10)
|
|
4
|
+
|
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.15.14...v3.16.0)
|
|
6
|
+
|
|
7
|
+
**Implemented enhancements:**
|
|
8
|
+
|
|
9
|
+
- Add `GoodJob.configure_active_record` as alternative to `GoodJob.active_record_parent_class` [\#1004](https://github.com/bensheldon/good_job/pull/1004) ([bensheldon](https://github.com/bensheldon))
|
|
10
|
+
- Configure `dashboard_default_locale` using custom subclass of `I18n::Config` to isolate I18n configuration from parent application [\#1001](https://github.com/bensheldon/good_job/pull/1001) ([bensheldon](https://github.com/bensheldon))
|
|
11
|
+
- Create `error_event` column to track the context of an error \(discarded, retried, retry\_stopped, etc\) [\#995](https://github.com/bensheldon/good_job/pull/995) ([bensheldon](https://github.com/bensheldon))
|
|
12
|
+
- Added metrics to Scheduler and track in Process state [\#984](https://github.com/bensheldon/good_job/pull/984) ([AndersGM](https://github.com/AndersGM))
|
|
13
|
+
|
|
14
|
+
**Fixed bugs:**
|
|
15
|
+
|
|
16
|
+
- Use Concurrent::Array for class `instances` to avoid JRuby synchronization errors [\#1002](https://github.com/bensheldon/good_job/pull/1002) ([bensheldon](https://github.com/bensheldon))
|
|
17
|
+
- Add test to assert enqueuing behavior within transactions [\#998](https://github.com/bensheldon/good_job/pull/998) ([bensheldon](https://github.com/bensheldon))
|
|
18
|
+
- Fix Ukrainian language code [\#996](https://github.com/bensheldon/good_job/pull/996) ([bensheldon](https://github.com/bensheldon))
|
|
19
|
+
|
|
20
|
+
**Closed issues:**
|
|
21
|
+
|
|
22
|
+
- Is `pgcrypto` necessary? [\#805](https://github.com/bensheldon/good_job/issues/805)
|
|
23
|
+
- Integrate Sorbet type checking [\#404](https://github.com/bensheldon/good_job/issues/404)
|
|
24
|
+
|
|
25
|
+
**Merged pull requests:**
|
|
26
|
+
|
|
27
|
+
- Unify `frozen_string_literal` comment style [\#1003](https://github.com/bensheldon/good_job/pull/1003) ([dixpac](https://github.com/dixpac))
|
|
28
|
+
- Add more execution mode details and caveats to Readme Set Up section [\#997](https://github.com/bensheldon/good_job/pull/997) ([bensheldon](https://github.com/bensheldon))
|
|
29
|
+
- Add note in migrations that `pgcrypto` extension isn't necessary in PG 13+ [\#837](https://github.com/bensheldon/good_job/pull/837) ([bensheldon](https://github.com/bensheldon))
|
|
30
|
+
- Add Sorbet to linter [\#760](https://github.com/bensheldon/good_job/pull/760) ([sam1el](https://github.com/sam1el))
|
|
31
|
+
|
|
32
|
+
## [v3.15.14](https://github.com/bensheldon/good_job/tree/v3.15.14) (2023-07-03)
|
|
33
|
+
|
|
34
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.15.13...v3.15.14)
|
|
35
|
+
|
|
36
|
+
**Implemented enhancements:**
|
|
37
|
+
|
|
38
|
+
- Add Process heartbeat that is updated inside of Notifier [\#977](https://github.com/bensheldon/good_job/pull/977) ([bensheldon](https://github.com/bensheldon))
|
|
39
|
+
|
|
40
|
+
**Fixed bugs:**
|
|
41
|
+
|
|
42
|
+
- Dashboard error when trying to display 0 running/queued/retried jobs due to missing 'zero' translation [\#990](https://github.com/bensheldon/good_job/issues/990)
|
|
43
|
+
- Add explicit namespace back to `GoodJob::DiscreteExecution` [\#983](https://github.com/bensheldon/good_job/pull/983) ([bensheldon](https://github.com/bensheldon))
|
|
44
|
+
|
|
45
|
+
**Closed issues:**
|
|
46
|
+
|
|
47
|
+
- Persisting ActiveSupport::CurrentAttributes [\#981](https://github.com/bensheldon/good_job/issues/981)
|
|
48
|
+
- uninitialized constant DiscreteExecution [\#962](https://github.com/bensheldon/good_job/issues/962)
|
|
49
|
+
- Hard kill resilience with execution counts [\#922](https://github.com/bensheldon/good_job/issues/922)
|
|
50
|
+
|
|
51
|
+
**Merged pull requests:**
|
|
52
|
+
|
|
53
|
+
- Bump rubocop from 1.53.0 to 1.54.0 [\#994](https://github.com/bensheldon/good_job/pull/994) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
54
|
+
- Bump rails from 7.0.5 to 7.0.6 [\#993](https://github.com/bensheldon/good_job/pull/993) ([dependabot[bot]](https://github.com/apps/dependabot))
|
|
55
|
+
- Fix CI: Lock traces version for Ruby 2.6 compatible version [\#987](https://github.com/bensheldon/good_job/pull/987) ([bensheldon](https://github.com/bensheldon))
|
|
56
|
+
- Turkish Language support [\#986](https://github.com/bensheldon/good_job/pull/986) ([SemihCag](https://github.com/SemihCag))
|
|
57
|
+
- Use generic error reporter in Readme examples [\#964](https://github.com/bensheldon/good_job/pull/964) ([shouichi](https://github.com/shouichi))
|
|
58
|
+
|
|
3
59
|
## [v3.15.13](https://github.com/bensheldon/good_job/tree/v3.15.13) (2023-06-14)
|
|
4
60
|
|
|
5
61
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.15.12...v3.15.13)
|
|
@@ -43,10 +99,6 @@
|
|
|
43
99
|
|
|
44
100
|
- Ensure migration warning for `DiscreteExecution` constant is in explicit `GoodJob::` namespace [\#963](https://github.com/bensheldon/good_job/pull/963) ([bensheldon](https://github.com/bensheldon))
|
|
45
101
|
|
|
46
|
-
**Closed issues:**
|
|
47
|
-
|
|
48
|
-
- uninitialized constant DiscreteExecution [\#962](https://github.com/bensheldon/good_job/issues/962)
|
|
49
|
-
|
|
50
102
|
## [v3.15.9](https://github.com/bensheldon/good_job/tree/v3.15.9) (2023-05-21)
|
|
51
103
|
|
|
52
104
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.15.8...v3.15.9)
|
data/README.md
CHANGED
|
@@ -121,8 +121,13 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
|
|
|
121
121
|
YourJob.set(queue: :some_queue, wait: 5.minutes, priority: 10).perform_later
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
1. In development, GoodJob executes jobs
|
|
125
|
-
|
|
124
|
+
1. **In Rails' development environment**, by default, GoodJob's Adapter executes jobs `async` in a background thread pool in `rails server`.
|
|
125
|
+
- Because of Rails deferred autoloading, jobs enqueued via the `rails console` may not begin executing on a separate server process until the Rails application is fully initialized by loading a web page once.
|
|
126
|
+
- Remember, only Active Job's `perform_later` sends jobs to the queue adapter; Active Job's `perform_now` executes the job immediately and does not invoke the queue adapter. GoodJob is not involved in `perform_now` jobs.
|
|
127
|
+
1. **In Rails' test environment**, by default, GoodJob's Adapter executes jobs `inline` immediately in the current thread.
|
|
128
|
+
- Future-scheduled jobs can be executed with `GoodJob.perform_inline` using using a tool like Timecop or `ActiveSupport::Testing::TimeHelpers`.
|
|
129
|
+
- Note that Active Job's TestAdapter, which powers test helpers (e.g. `assert_enqueued_with`), may override GoodJob's Adapter in [some configurations](https://github.com/rails/rails/issues/37270).
|
|
130
|
+
1. **In Rails' production environment**, by default, GoodJob's Adapter enqueues jobs in `external` mode to be executed by a separate execution process:
|
|
126
131
|
- By default, GoodJob separates job enqueuing from job execution so that jobs can be scaled independently of the web server. Use the GoodJob command-line tool to execute jobs:
|
|
127
132
|
|
|
128
133
|
```bash
|
|
@@ -231,7 +236,7 @@ Rails.application.configure do
|
|
|
231
236
|
# Configure options individually...
|
|
232
237
|
config.good_job.preserve_job_records = true
|
|
233
238
|
config.good_job.retry_on_unhandled_error = false
|
|
234
|
-
config.good_job.on_thread_error = -> (exception) {
|
|
239
|
+
config.good_job.on_thread_error = -> (exception) { Rails.error.report(exception) }
|
|
235
240
|
config.good_job.execution_mode = :async
|
|
236
241
|
config.good_job.queues = '*'
|
|
237
242
|
config.good_job.max_threads = 5
|
|
@@ -239,12 +244,13 @@ Rails.application.configure do
|
|
|
239
244
|
config.good_job.shutdown_timeout = 25 # seconds
|
|
240
245
|
config.good_job.enable_cron = true
|
|
241
246
|
config.good_job.cron = { example: { cron: '0 * * * *', class: 'ExampleJob' } }
|
|
247
|
+
config.good_job.dashboard_default_locale = :en
|
|
242
248
|
|
|
243
249
|
# ...or all at once.
|
|
244
250
|
config.good_job = {
|
|
245
251
|
preserve_job_records: true,
|
|
246
252
|
retry_on_unhandled_error: false,
|
|
247
|
-
on_thread_error: -> (exception) {
|
|
253
|
+
on_thread_error: -> (exception) { Rails.error.report(exception) },
|
|
248
254
|
execution_mode: :async,
|
|
249
255
|
queues: '*',
|
|
250
256
|
max_threads: 5,
|
|
@@ -257,6 +263,7 @@ Rails.application.configure do
|
|
|
257
263
|
class: 'ExampleJob'
|
|
258
264
|
},
|
|
259
265
|
},
|
|
266
|
+
dashboard_default_locale: :en,
|
|
260
267
|
}
|
|
261
268
|
end
|
|
262
269
|
```
|
|
@@ -287,7 +294,7 @@ Available configuration options are:
|
|
|
287
294
|
- `on_thread_error` (proc, lambda, or callable) will be called when there is an Exception. It can be useful for logging errors to bug tracking services, like Sentry or Airbrake. Example:
|
|
288
295
|
|
|
289
296
|
```ruby
|
|
290
|
-
config.good_job.on_thread_error = -> (exception) {
|
|
297
|
+
config.good_job.on_thread_error = -> (exception) { Rails.error.report(exception) }
|
|
291
298
|
```
|
|
292
299
|
|
|
293
300
|
By default, GoodJob configures the following execution modes per environment:
|
|
@@ -311,7 +318,17 @@ config.good_job.execution_mode = :external
|
|
|
311
318
|
|
|
312
319
|
Good Job’s general behavior can also be configured via attributes directly on the `GoodJob` module:
|
|
313
320
|
|
|
314
|
-
- **`GoodJob.
|
|
321
|
+
- **`GoodJob.configure_active_record { ... }`** Inject Active Record configuration into GoodJob's base model, for example, when using [multiple databases with ActiveRecord](https://guides.rubyonrails.org/active_record_multiple_databases.html) or when other custom configuration is necessary for the ActiveRecord model to connect to the Postgres database. Example:
|
|
322
|
+
|
|
323
|
+
```ruby
|
|
324
|
+
# config/initializers/good_job.rb
|
|
325
|
+
GoodJob.configure_active_record do
|
|
326
|
+
connects_to database: :special_database
|
|
327
|
+
self.table_name_prefix = "special_application_"
|
|
328
|
+
end
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
- **`GoodJob.active_record_parent_class`** (string) Alternatively, modify the ActiveRecord parent class inherited by GoodJob's Active Record model `GoodJob::Job` (defaults to `"ActiveRecord::Base"`). Configure this _The value must be a String to avoid premature initialization of ActiveRecord._
|
|
315
332
|
|
|
316
333
|
You’ll generally want to configure these in `config/initializers/good_job.rb`, like so:
|
|
317
334
|
|
|
@@ -760,7 +777,7 @@ If errors do reach GoodJob, you can assign a callable to `GoodJob.on_thread_erro
|
|
|
760
777
|
|
|
761
778
|
```ruby
|
|
762
779
|
# config/initializers/good_job.rb
|
|
763
|
-
GoodJob.on_thread_error = -> (exception) {
|
|
780
|
+
GoodJob.on_thread_error = -> (exception) { Rails.error.report(exception) }
|
|
764
781
|
```
|
|
765
782
|
|
|
766
783
|
#### Retries
|
|
@@ -794,13 +811,13 @@ class ApplicationJob < ActiveJob::Base
|
|
|
794
811
|
retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
|
|
795
812
|
|
|
796
813
|
retry_on SpecialError, attempts: 5 do |_job, exception|
|
|
797
|
-
|
|
814
|
+
Rails.error.report(exception)
|
|
798
815
|
end
|
|
799
816
|
|
|
800
817
|
around_perform do |_job, block|
|
|
801
818
|
block.call
|
|
802
819
|
rescue StandardError => e
|
|
803
|
-
|
|
820
|
+
Rails.error.report(e)
|
|
804
821
|
raise
|
|
805
822
|
end
|
|
806
823
|
# ...
|
|
@@ -823,7 +840,7 @@ ActionMailer::MailDeliveryJob.retry_on StandardError, wait: :exponentially_longe
|
|
|
823
840
|
ActionMailer::MailDeliveryJob.around_perform do |_job, block|
|
|
824
841
|
block.call
|
|
825
842
|
rescue StandardError => e
|
|
826
|
-
|
|
843
|
+
Rails.error.report(e)
|
|
827
844
|
raise
|
|
828
845
|
end
|
|
829
846
|
```
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GoodJob
|
|
3
4
|
class ApplicationController < ActionController::Base
|
|
4
5
|
protect_from_forgery with: :exception
|
|
5
6
|
|
|
6
|
-
around_action :
|
|
7
|
+
around_action :use_good_job_locale
|
|
7
8
|
|
|
8
9
|
content_security_policy do |policy|
|
|
9
10
|
policy.default_src(:none) if policy.default_src(*policy.default_src).blank?
|
|
@@ -30,8 +31,21 @@ module GoodJob
|
|
|
30
31
|
{ locale: I18n.locale }.merge(options)
|
|
31
32
|
end
|
|
32
33
|
|
|
33
|
-
def
|
|
34
|
+
def use_good_job_locale(&action)
|
|
35
|
+
@original_i18n_config = I18n.config
|
|
36
|
+
I18n.config = ::GoodJob::I18nConfig.new
|
|
34
37
|
I18n.with_locale(current_locale, &action)
|
|
38
|
+
ensure
|
|
39
|
+
I18n.config = @original_i18n_config
|
|
40
|
+
@original_i18n_config = nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def use_original_locale
|
|
44
|
+
prev_config = I18n.config
|
|
45
|
+
I18n.config = @original_i18n_config if @original_i18n_config
|
|
46
|
+
yield
|
|
47
|
+
ensure
|
|
48
|
+
I18n.config = prev_config
|
|
35
49
|
end
|
|
36
50
|
|
|
37
51
|
def current_locale
|
|
@@ -39,16 +53,9 @@ module GoodJob
|
|
|
39
53
|
request.GET['locale']
|
|
40
54
|
elsif params[:locale]
|
|
41
55
|
params[:locale]
|
|
42
|
-
elsif good_job_available_locales.exclude?(I18n.default_locale) && I18n.available_locales.include?(:en)
|
|
43
|
-
:en
|
|
44
56
|
else
|
|
45
57
|
I18n.default_locale
|
|
46
58
|
end
|
|
47
59
|
end
|
|
48
|
-
|
|
49
|
-
def good_job_available_locales
|
|
50
|
-
@_good_job_available_locales ||= GoodJob::Engine.root.join("config/locales").glob("*.yml").map { |path| File.basename(path, ".yml").to_sym }.uniq
|
|
51
|
-
end
|
|
52
|
-
helper_method :good_job_available_locales
|
|
53
60
|
end
|
|
54
61
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GoodJob
|
|
3
4
|
class CronEntriesController < GoodJob::ApplicationController
|
|
4
5
|
before_action :check_settings_migration!, only: [:enable, :disable]
|
|
@@ -14,7 +15,7 @@ module GoodJob
|
|
|
14
15
|
|
|
15
16
|
def enqueue
|
|
16
17
|
@cron_entry = CronEntry.find(params[:cron_key])
|
|
17
|
-
@cron_entry.enqueue(Time.current)
|
|
18
|
+
use_original_locale { @cron_entry.enqueue(Time.current) }
|
|
18
19
|
redirect_back(fallback_location: cron_entries_path, notice: t(".notice"))
|
|
19
20
|
end
|
|
20
21
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GoodJob
|
|
3
4
|
module ApplicationHelper
|
|
4
5
|
def format_duration(sec)
|
|
@@ -63,7 +64,6 @@ module GoodJob
|
|
|
63
64
|
end
|
|
64
65
|
|
|
65
66
|
def translation_exists?(key, **options)
|
|
66
|
-
true if good_job_available_locales.include?(I18n.locale)
|
|
67
67
|
I18n.exists?(scope_key_by_partial(key), **options)
|
|
68
68
|
end
|
|
69
69
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GoodJob
|
|
4
|
+
# Shared methods for filtering Execution/Job records from the +good_jobs+ table.
|
|
5
|
+
module ErrorEvents
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
ERROR_EVENTS = [
|
|
9
|
+
ERROR_EVENT_INTERRUPTED = 'interrupted',
|
|
10
|
+
ERROR_EVENT_UNHANDLED = 'unhandled',
|
|
11
|
+
ERROR_EVENT_HANDLED = 'handled',
|
|
12
|
+
ERROR_EVENT_RETRIED = 'retried',
|
|
13
|
+
ERROR_EVENT_RETRY_STOPPED = 'retry_stopped',
|
|
14
|
+
ERROR_EVENT_DISCARDED = 'discarded',
|
|
15
|
+
].freeze
|
|
16
|
+
|
|
17
|
+
included do
|
|
18
|
+
enum error_event: {
|
|
19
|
+
ERROR_EVENT_INTERRUPTED => 0,
|
|
20
|
+
ERROR_EVENT_UNHANDLED => 1,
|
|
21
|
+
ERROR_EVENT_HANDLED => 2,
|
|
22
|
+
ERROR_EVENT_RETRIED => 3,
|
|
23
|
+
ERROR_EVENT_RETRY_STOPPED => 4,
|
|
24
|
+
ERROR_EVENT_DISCARDED => 5,
|
|
25
|
+
}.freeze, _prefix: :error_event
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -4,6 +4,8 @@ module GoodJob
|
|
|
4
4
|
# ActiveRecord model to share behavior between {Job} and {Execution} models
|
|
5
5
|
# which both read out of the same table.
|
|
6
6
|
class BaseExecution < BaseRecord
|
|
7
|
+
include ErrorEvents
|
|
8
|
+
|
|
7
9
|
self.table_name = 'good_jobs'
|
|
8
10
|
|
|
9
11
|
# With a given class name
|
|
@@ -35,7 +37,14 @@ module GoodJob
|
|
|
35
37
|
end
|
|
36
38
|
|
|
37
39
|
def discrete_support?
|
|
38
|
-
DiscreteExecution.migrated?
|
|
40
|
+
GoodJob::DiscreteExecution.migrated?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def error_event_migrated?
|
|
44
|
+
return true if columns_hash["error_event"].present?
|
|
45
|
+
|
|
46
|
+
migration_pending_warning!
|
|
47
|
+
false
|
|
39
48
|
end
|
|
40
49
|
end
|
|
41
50
|
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GoodJob
|
|
3
4
|
# Base ActiveRecord class that all GoodJob models inherit from.
|
|
4
5
|
# Parent class can be configured with +GoodJob.active_record_parent_class+.
|
|
5
6
|
# @!parse
|
|
6
7
|
# class BaseRecord < ActiveRecord::Base; end
|
|
7
|
-
class BaseRecord <
|
|
8
|
+
class BaseRecord < ActiveRecordParentClass
|
|
8
9
|
self.abstract_class = true
|
|
9
10
|
|
|
10
11
|
def self.migration_pending_warning!
|
|
@@ -26,5 +27,7 @@ module GoodJob
|
|
|
26
27
|
migration_pending_warning!
|
|
27
28
|
false
|
|
28
29
|
end
|
|
30
|
+
|
|
31
|
+
ActiveSupport.run_load_hooks(:good_job_base_record, self)
|
|
29
32
|
end
|
|
30
33
|
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module GoodJob # :nodoc:
|
|
4
4
|
class DiscreteExecution < BaseRecord
|
|
5
|
+
include ErrorEvents
|
|
6
|
+
|
|
5
7
|
self.table_name = 'good_job_executions'
|
|
6
8
|
|
|
7
9
|
belongs_to :execution, class_name: 'GoodJob::Execution', foreign_key: 'active_job_id', primary_key: 'active_job_id', inverse_of: :discrete_executions, optional: true
|
|
@@ -11,6 +13,13 @@ module GoodJob # :nodoc:
|
|
|
11
13
|
|
|
12
14
|
alias_attribute :performed_at, :created_at
|
|
13
15
|
|
|
16
|
+
def self.error_event_migrated?
|
|
17
|
+
return true if columns_hash["error_event"].present?
|
|
18
|
+
|
|
19
|
+
migration_pending_warning!
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
|
|
14
23
|
def number
|
|
15
24
|
serialized_params.fetch('executions', 0) + 1
|
|
16
25
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GoodJob
|
|
3
4
|
# ActiveRecord model that represents an +ActiveJob+ job.
|
|
4
5
|
class Execution < BaseExecution
|
|
@@ -262,7 +263,11 @@ module GoodJob
|
|
|
262
263
|
unfinished.dequeueing_ordered(parsed_queues).only_scheduled.limit(1).with_advisory_lock(unlock_session: true, select_limit: queue_select_limit) do |executions|
|
|
263
264
|
execution = executions.first
|
|
264
265
|
break if execution.blank?
|
|
265
|
-
|
|
266
|
+
|
|
267
|
+
unless execution.executable?
|
|
268
|
+
result = ExecutionResult.new(value: nil, unexecutable: true)
|
|
269
|
+
break
|
|
270
|
+
end
|
|
266
271
|
|
|
267
272
|
yield(execution) if block_given?
|
|
268
273
|
result = execution.perform
|
|
@@ -373,10 +378,14 @@ module GoodJob
|
|
|
373
378
|
if discrete?
|
|
374
379
|
interrupt_error_string = self.class.format_error(GoodJob::InterruptError.new("Interrupted after starting perform at '#{performed_at}'"))
|
|
375
380
|
self.error = interrupt_error_string
|
|
376
|
-
|
|
381
|
+
self.error_event = ERROR_EVENT_INTERRUPTED if self.class.error_event_migrated?
|
|
382
|
+
|
|
383
|
+
discrete_execution_attrs = {
|
|
377
384
|
error: interrupt_error_string,
|
|
378
|
-
finished_at: Time.current
|
|
379
|
-
|
|
385
|
+
finished_at: Time.current,
|
|
386
|
+
}
|
|
387
|
+
discrete_execution_attrs[:error_event] = GoodJob::DiscreteExecution.error_events[GoodJob::DiscreteExecution::ERROR_EVENT_INTERRUPTED] if self.class.error_event_migrated?
|
|
388
|
+
discrete_executions.where(finished_at: nil).where.not(performed_at: nil).update_all(discrete_execution_attrs) # rubocop:disable Rails/SkipsModelValidations
|
|
380
389
|
end
|
|
381
390
|
end
|
|
382
391
|
|
|
@@ -405,15 +414,34 @@ module GoodJob
|
|
|
405
414
|
end
|
|
406
415
|
handled_error ||= current_thread.error_on_retry || current_thread.error_on_discard
|
|
407
416
|
|
|
417
|
+
error_event = if handled_error == current_thread.error_on_discard
|
|
418
|
+
ERROR_EVENT_DISCARDED
|
|
419
|
+
elsif handled_error == current_thread.error_on_retry
|
|
420
|
+
ERROR_EVENT_RETRIED
|
|
421
|
+
elsif handled_error == current_thread.error_on_retry_stopped
|
|
422
|
+
ERROR_EVENT_RETRY_STOPPED
|
|
423
|
+
elsif handled_error
|
|
424
|
+
ERROR_EVENT_HANDLED
|
|
425
|
+
end
|
|
426
|
+
|
|
408
427
|
instrument_payload.merge!(
|
|
409
428
|
value: value,
|
|
410
429
|
handled_error: handled_error,
|
|
411
|
-
retried: current_thread.execution_retried
|
|
430
|
+
retried: current_thread.execution_retried,
|
|
431
|
+
error_event: error_event
|
|
412
432
|
)
|
|
413
|
-
ExecutionResult.new(value: value, handled_error: handled_error, retried: current_thread.execution_retried)
|
|
433
|
+
ExecutionResult.new(value: value, handled_error: handled_error, error_event: error_event, retried: current_thread.execution_retried)
|
|
414
434
|
rescue StandardError => e
|
|
435
|
+
error_event = if e.is_a?(GoodJob::InterruptError)
|
|
436
|
+
ERROR_EVENT_INTERRUPTED
|
|
437
|
+
elsif e == current_thread.error_on_retry_stopped
|
|
438
|
+
ERROR_EVENT_RETRY_STOPPED
|
|
439
|
+
else
|
|
440
|
+
ERROR_EVENT_UNHANDLED
|
|
441
|
+
end
|
|
442
|
+
|
|
415
443
|
instrument_payload[:unhandled_error] = e
|
|
416
|
-
ExecutionResult.new(value: nil, unhandled_error: e)
|
|
444
|
+
ExecutionResult.new(value: nil, unhandled_error: e, error_event: error_event)
|
|
417
445
|
end
|
|
418
446
|
end
|
|
419
447
|
|
|
@@ -422,9 +450,14 @@ module GoodJob
|
|
|
422
450
|
if job_error
|
|
423
451
|
error_string = self.class.format_error(job_error)
|
|
424
452
|
self.error = error_string
|
|
425
|
-
|
|
453
|
+
self.error_event = result.error_event if self.class.error_event_migrated?
|
|
454
|
+
if discrete_execution
|
|
455
|
+
discrete_execution.error = error_string
|
|
456
|
+
discrete_execution.error_event = result.error_event if discrete_execution.class.error_event_migrated?
|
|
457
|
+
end
|
|
426
458
|
else
|
|
427
459
|
self.error = nil
|
|
460
|
+
self.error_event = nil if self.class.error_event_migrated?
|
|
428
461
|
end
|
|
429
462
|
|
|
430
463
|
reenqueued = result.retried? || retried_good_job_id.present?
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GoodJob
|
|
3
4
|
# Stores the results of job execution
|
|
4
5
|
class ExecutionResult
|
|
@@ -8,18 +9,32 @@ module GoodJob
|
|
|
8
9
|
attr_reader :handled_error
|
|
9
10
|
# @return [Exception, nil]
|
|
10
11
|
attr_reader :unhandled_error
|
|
11
|
-
# @return [
|
|
12
|
+
# @return [String, nil]
|
|
13
|
+
attr_reader :error_event
|
|
14
|
+
# @return [Boolean, nil]
|
|
15
|
+
attr_reader :unexecutable
|
|
16
|
+
# @return [Boolean, nil]
|
|
12
17
|
attr_reader :retried
|
|
13
18
|
alias retried? retried
|
|
14
19
|
|
|
15
20
|
# @param value [Object, nil]
|
|
16
21
|
# @param handled_error [Exception, nil]
|
|
17
22
|
# @param unhandled_error [Exception, nil]
|
|
18
|
-
|
|
23
|
+
# @param error_event [String, nil]
|
|
24
|
+
# @param unexecutable [Boolean, nil]
|
|
25
|
+
# @param retried [Boolean, nil]
|
|
26
|
+
def initialize(value:, handled_error: nil, unhandled_error: nil, error_event: nil, unexecutable: nil, retried: false)
|
|
19
27
|
@value = value
|
|
20
28
|
@handled_error = handled_error
|
|
21
29
|
@unhandled_error = unhandled_error
|
|
30
|
+
@error_event = error_event
|
|
31
|
+
@unexecutable = unexecutable
|
|
22
32
|
@retried = retried
|
|
23
33
|
end
|
|
34
|
+
|
|
35
|
+
# @return [Boolean]
|
|
36
|
+
def succeeded?
|
|
37
|
+
!(handled_error || unhandled_error || unexecutable || retried)
|
|
38
|
+
end
|
|
24
39
|
end
|
|
25
40
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GoodJob
|
|
4
|
+
class I18nConfig < ::I18n::Config
|
|
5
|
+
BACKEND = I18n::Backend::Simple.new
|
|
6
|
+
AVAILABLE_LOCALES = GoodJob::Engine.root.join("config/locales").glob("*.yml").map { |path| File.basename(path, ".yml").to_sym }.uniq
|
|
7
|
+
AVAILABLE_LOCALES_SET = AVAILABLE_LOCALES.inject(Set.new) { |set, locale| set << locale.to_s << locale.to_sym }
|
|
8
|
+
|
|
9
|
+
def backend
|
|
10
|
+
BACKEND
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def available_locales
|
|
14
|
+
AVAILABLE_LOCALES
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def available_locales_set
|
|
18
|
+
AVAILABLE_LOCALES_SET
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def default_locale
|
|
22
|
+
GoodJob.configuration.dashboard_default_locale
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/app/models/good_job/job.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module GoodJob
|
|
3
4
|
# ActiveRecord model that represents an +ActiveJob+ job.
|
|
4
5
|
# There is not a table in the database whose discrete rows represents "Jobs".
|
|
@@ -198,6 +199,7 @@ module GoodJob
|
|
|
198
199
|
|
|
199
200
|
execution.class.transaction(joinable: false, requires_new: true) do
|
|
200
201
|
new_active_job = active_job.retry_job(wait: 0, error: execution.error)
|
|
202
|
+
execution.error_event = ERROR_EVENT_RETRIED if execution.error && execution.class.error_event_migrated?
|
|
201
203
|
execution.save!
|
|
202
204
|
end
|
|
203
205
|
end
|
|
@@ -221,7 +223,8 @@ module GoodJob
|
|
|
221
223
|
update_execution = proc do
|
|
222
224
|
execution.update(
|
|
223
225
|
finished_at: Time.current,
|
|
224
|
-
error: GoodJob::Execution.format_error(job_error)
|
|
226
|
+
error: GoodJob::Execution.format_error(job_error),
|
|
227
|
+
error_event: :discarded
|
|
225
228
|
)
|
|
226
229
|
end
|
|
227
230
|
|