good_job 3.21.5 → 3.22.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 +32 -0
- data/README.md +54 -29
- data/app/controllers/good_job/jobs_controller.rb +1 -1
- data/app/models/concerns/good_job/filterable.rb +1 -1
- data/app/models/good_job/base_execution.rb +23 -1
- data/app/models/good_job/execution.rb +11 -4
- data/app/models/good_job/job.rb +4 -4
- data/app/views/good_job/shared/_footer.erb +1 -9
- data/app/views/good_job/shared/_navbar.erb +1 -1
- data/app/views/good_job/shared/_secondary_navbar.erb +11 -0
- data/app/views/layouts/good_job/application.html.erb +34 -39
- data/config/locales/de.yml +3 -3
- data/config/locales/en.yml +3 -3
- data/config/locales/es.yml +3 -3
- data/config/locales/fr.yml +3 -3
- data/config/locales/ja.yml +3 -3
- data/config/locales/nl.yml +3 -3
- data/config/locales/ru.yml +3 -3
- data/config/locales/tr.yml +3 -3
- data/config/locales/uk.yml +3 -3
- data/lib/generators/good_job/templates/install/migrations/create_good_jobs.rb.erb +2 -1
- data/lib/generators/good_job/templates/update/migrations/08_create_good_job_labels.rb.erb +15 -0
- data/lib/generators/good_job/templates/update/migrations/09_create_good_job_labels_index.rb.erb +22 -0
- data/lib/generators/good_job/templates/update/migrations/10_remove_good_job_active_id_index.rb.erb +21 -0
- data/lib/good_job/active_job_extensions/labels.rb +32 -0
- data/lib/good_job/version.rb +1 -1
- data/lib/good_job.rb +3 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 699ef4a7d62e1eb7c96644525c9e2239913fb5d23ceafacb13be172e96720532
|
4
|
+
data.tar.gz: dcfe3389202698fa321d4c10349758766db20811feafb10024373d54c94dcd2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77215885e8d798ba791814bb64f07f2c70d54fa0dd3bb9bbc476dc0464d4c150089bf466e4ed16b648425f78eb9b7e86f0b1259f19e166633f60619347ea3281
|
7
|
+
data.tar.gz: 8f1b9a3e16080e331581efbe48bea5060666c4eda460737e1a34508ee6d278abc1fea91e68d486759f39a082b1969c87f84e22a620d7598bc4f9b93d69fce7d8
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,37 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v3.22.0](https://github.com/bensheldon/good_job/tree/v3.22.0) (2024-01-03)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.21.5...v3.22.0)
|
6
|
+
|
7
|
+
**Implemented enhancements:**
|
8
|
+
|
9
|
+
- Add "updated at" info in secondary top navbar [\#1204](https://github.com/bensheldon/good_job/pull/1204) ([sparshalc](https://github.com/sparshalc))
|
10
|
+
- Re-add footer with GoodJob version number [\#1201](https://github.com/bensheldon/good_job/pull/1201) ([Pauloparakleto](https://github.com/Pauloparakleto))
|
11
|
+
- Add Active Job extension for Labels [\#1188](https://github.com/bensheldon/good_job/pull/1188) ([bensheldon](https://github.com/bensheldon))
|
12
|
+
|
13
|
+
**Closed issues:**
|
14
|
+
|
15
|
+
- Limiting by executed jobs count by period [\#1198](https://github.com/bensheldon/good_job/issues/1198)
|
16
|
+
- Cron jobs processing in async mode [\#1196](https://github.com/bensheldon/good_job/issues/1196)
|
17
|
+
- Dashboard Missing Translation? [\#1192](https://github.com/bensheldon/good_job/issues/1192)
|
18
|
+
- Show last update on top nav bar [\#1183](https://github.com/bensheldon/good_job/issues/1183)
|
19
|
+
- Wrong quoting of the query to spot new jobs? [\#1179](https://github.com/bensheldon/good_job/issues/1179)
|
20
|
+
- \[Possible bug\] good\_job does not honour the wait parameter on retry\_on [\#1174](https://github.com/bensheldon/good_job/issues/1174)
|
21
|
+
- Running GoodJob in production with systemd throws an error due to a wrong communication with WatchDog [\#1172](https://github.com/bensheldon/good_job/issues/1172)
|
22
|
+
|
23
|
+
**Merged pull requests:**
|
24
|
+
|
25
|
+
- Bump the bundler-dependencies group with 3 updates [\#1202](https://github.com/bensheldon/good_job/pull/1202) ([dependabot[bot]](https://github.com/apps/dependabot))
|
26
|
+
- Remove duplicated intro sentence in README [\#1195](https://github.com/bensheldon/good_job/pull/1195) ([benoittgt](https://github.com/benoittgt))
|
27
|
+
- Fix namespace for `InterruptError` in README [\#1193](https://github.com/bensheldon/good_job/pull/1193) ([padde](https://github.com/padde))
|
28
|
+
- Bump github/codeql-action from 2 to 3 [\#1191](https://github.com/bensheldon/good_job/pull/1191) ([dependabot[bot]](https://github.com/apps/dependabot))
|
29
|
+
- Bump actions/upload-artifact from 3 to 4 [\#1190](https://github.com/bensheldon/good_job/pull/1190) ([dependabot[bot]](https://github.com/apps/dependabot))
|
30
|
+
- Lock RubyGems version for Ruby \< 3.0 in CI [\#1189](https://github.com/bensheldon/good_job/pull/1189) ([bensheldon](https://github.com/bensheldon))
|
31
|
+
- Active Record and Active Job name formatting [\#1182](https://github.com/bensheldon/good_job/pull/1182) ([andyatkinson](https://github.com/andyatkinson))
|
32
|
+
- Remove redundant `good_jobs.active_job_id` index [\#1181](https://github.com/bensheldon/good_job/pull/1181) ([andyatkinson](https://github.com/andyatkinson))
|
33
|
+
- Add missing word in readme [\#1177](https://github.com/bensheldon/good_job/pull/1177) ([Earlopain](https://github.com/Earlopain))
|
34
|
+
|
3
35
|
## [v3.21.5](https://github.com/bensheldon/good_job/tree/v3.21.5) (2023-12-12)
|
4
36
|
|
5
37
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.21.4...v3.21.5)
|
data/README.md
CHANGED
@@ -4,11 +4,11 @@
|
|
4
4
|
[![Test Status](https://github.com/bensheldon/good_job/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/bensheldon/good_job/actions/workflows/test.yml?query=branch%3Amain)
|
5
5
|
[![Ruby Toolbox](https://img.shields.io/badge/dynamic/json?color=blue&label=Ruby%20Toolbox&query=%24.projects%5B0%5D.score&url=https%3A%2F%2Fwww.ruby-toolbox.com%2Fapi%2Fprojects%2Fcompare%2Fgood_job&logo=data:image/svg+xml;base64,PHN2ZyBhcmlhLWhpZGRlbj0idHJ1ZSIgZm9jdXNhYmxlPSJmYWxzZSIgZGF0YS1wcmVmaXg9ImZhcyIgZGF0YS1pY29uPSJmbGFzayIgY2xhc3M9InN2Zy1pbmxpbmUtLWZhIGZhLWZsYXNrIGZhLXctMTQiIHJvbGU9ImltZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDQ4IDUxMiI+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik00MzcuMiA0MDMuNUwzMjAgMjE1VjY0aDhjMTMuMyAwIDI0LTEwLjcgMjQtMjRWMjRjMC0xMy4zLTEwLjctMjQtMjQtMjRIMTIwYy0xMy4zIDAtMjQgMTAuNy0yNCAyNHYxNmMwIDEzLjMgMTAuNyAyNCAyNCAyNGg4djE1MUwxMC44IDQwMy41Qy0xOC41IDQ1MC42IDE1LjMgNTEyIDcwLjkgNTEyaDMwNi4yYzU1LjcgMCA4OS40LTYxLjUgNjAuMS0xMDguNXpNMTM3LjkgMzIwbDQ4LjItNzcuNmMzLjctNS4yIDUuOC0xMS42IDUuOC0xOC40VjY0aDY0djE2MGMwIDYuOSAyLjIgMTMuMiA1LjggMTguNGw0OC4yIDc3LjZoLTE3MnoiPjwvcGF0aD48L3N2Zz4=)](https://www.ruby-toolbox.com/projects/good_job)
|
6
6
|
|
7
|
-
GoodJob is a multithreaded, Postgres-based,
|
7
|
+
GoodJob is a multithreaded, Postgres-based, Active Job backend for Ruby on Rails.
|
8
8
|
|
9
|
-
**Inspired by [Delayed::Job](https://github.com/collectiveidea/delayed_job) and [Que](https://github.com/que-rb/que), GoodJob is designed for maximum compatibility with Ruby on Rails,
|
9
|
+
**Inspired by [Delayed::Job](https://github.com/collectiveidea/delayed_job) and [Que](https://github.com/que-rb/que), GoodJob is designed for maximum compatibility with Ruby on Rails, Active Job, and Postgres to be simple and performant for most workloads.**
|
10
10
|
|
11
|
-
- **Designed for
|
11
|
+
- **Designed for Active Job.** Complete support for [async, queues, delays, priorities, timeouts, and retries](https://edgeguides.rubyonrails.org/active_job_basics.html) with near-zero configuration.
|
12
12
|
- **Built for Rails.** Fully adopts Ruby on Rails [threading and code execution guidelines](https://guides.rubyonrails.org/threading_and_code_execution.html) with [Concurrent::Ruby](https://github.com/ruby-concurrency/concurrent-ruby).
|
13
13
|
- **Backed by Postgres.** Relies upon Postgres integrity, session-level Advisory Locks to provide run-once safety and stay within the limits of `schema.rb`, and LISTEN/NOTIFY to reduce queuing latency.
|
14
14
|
- **For most workloads.** Targets full-stack teams, economy-minded solo developers, and applications that enqueue 1-million jobs/day and more.
|
@@ -55,7 +55,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
|
|
55
55
|
- [Exceptions, retries, and reliability](#exceptions-retries-and-reliability)
|
56
56
|
- [Exceptions](#exceptions)
|
57
57
|
- [Retries](#retries)
|
58
|
-
- [
|
58
|
+
- [Action Mailer retries](#action-mailer-retries)
|
59
59
|
- [Interrupts](#interrupts)
|
60
60
|
- [Timeouts](#timeouts)
|
61
61
|
- [Optimize queues, threads, and processes](#optimize-queues-threads-and-processes)
|
@@ -63,7 +63,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
|
|
63
63
|
- [Production setup](#production-setup)
|
64
64
|
- [Queue performance with Queue Select Limit](#queue-performance-with-queue-select-limit)
|
65
65
|
- [Execute jobs async / in-process](#execute-jobs-async--in-process)
|
66
|
-
- [Migrate to GoodJob from a different
|
66
|
+
- [Migrate to GoodJob from a different Active Job backend](#migrate-to-goodjob-from-a-different-active-job-backend)
|
67
67
|
- [Monitor and preserve worked jobs](#monitor-and-preserve-worked-jobs)
|
68
68
|
- [Write tests](#write-tests)
|
69
69
|
- [PgBouncer compatibility](#pgbouncer-compatibility)
|
@@ -103,7 +103,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
|
|
103
103
|
bin/rails db:migrate:animals
|
104
104
|
```
|
105
105
|
|
106
|
-
1. Configure the
|
106
|
+
1. Configure the Active Job adapter:
|
107
107
|
|
108
108
|
```ruby
|
109
109
|
# config/application.rb or config/environments/{RAILS_ENV}.rb
|
@@ -116,7 +116,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
|
|
116
116
|
YourJob.perform_later
|
117
117
|
```
|
118
118
|
|
119
|
-
GoodJob supports all
|
119
|
+
GoodJob supports all Active Job features:
|
120
120
|
|
121
121
|
```ruby
|
122
122
|
YourJob.set(queue: :some_queue, wait: 5.minutes, priority: 10).perform_later
|
@@ -222,7 +222,7 @@ and this command is not required to be used.
|
|
222
222
|
|
223
223
|
### Configuration options
|
224
224
|
|
225
|
-
|
225
|
+
Active Job configuration depends on where the code is placed:
|
226
226
|
|
227
227
|
- `config.active_job.queue_adapter = :good_job` within `config/application.rb` or `config/environments/*.rb`.
|
228
228
|
- `ActiveJob::Base.queue_adapter = :good_job` within an initializer (e.g. `config/initializers/active_job.rb`).
|
@@ -321,7 +321,7 @@ config.good_job.execution_mode = :external
|
|
321
321
|
|
322
322
|
Good Job’s general behavior can also be configured via attributes directly on the `GoodJob` module:
|
323
323
|
|
324
|
-
- **`GoodJob.configure_active_record { ... }`** Inject Active Record configuration into GoodJob's base model, for example, when using [multiple databases with
|
324
|
+
- **`GoodJob.configure_active_record { ... }`** Inject Active Record configuration into GoodJob's base model, for example, when using [multiple databases with Active Record](https://guides.rubyonrails.org/active_record_multiple_databases.html) or when other custom configuration is necessary for the Active Record model to connect to the Postgres database. Example:
|
325
325
|
|
326
326
|
```ruby
|
327
327
|
# config/initializers/good_job.rb
|
@@ -331,7 +331,7 @@ Good Job’s general behavior can also be configured via attributes directly on
|
|
331
331
|
end
|
332
332
|
```
|
333
333
|
|
334
|
-
- **`GoodJob.active_record_parent_class`** (string) Alternatively, modify the
|
334
|
+
- **`GoodJob.active_record_parent_class`** (string) Alternatively, modify the Active Record 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 Active Record._
|
335
335
|
|
336
336
|
You’ll generally want to configure these in `config/initializers/good_job.rb`, like so:
|
337
337
|
|
@@ -438,9 +438,34 @@ The Dashboard can be set to automatically refresh by checking "Live Poll" in the
|
|
438
438
|
|
439
439
|
Higher priority numbers run first in all versions of GoodJob v3.x and below. GoodJob v4.x will change job `priority` to give smaller numbers higher priority (default: `0`), in accordance with Active Job's definition of priority (see #524). To opt-in to this behavior now, set `config.good_job.smaller_number_is_higher_priority = true` in your GoodJob initializer or `application.rb`.
|
440
440
|
|
441
|
+
### Labelled jobs
|
442
|
+
|
443
|
+
Labels are the recommended way to add context or metadata to specific jobs. For example, all jobs that have a dependency on an email service could be labeled `email`. Using labels requires adding the Active Job extension `GoodJob::ActiveJobExtensions::Labels` to your job class.
|
444
|
+
|
445
|
+
```ruby
|
446
|
+
class ApplicationRecord < ActiveJob::Base
|
447
|
+
include GoodJob::ActiveJobExtensions::Labels
|
448
|
+
end
|
449
|
+
|
450
|
+
# Add a default label to every job within the class
|
451
|
+
class WelcomeJob < ApplicationRecord
|
452
|
+
self.good_job_labels = ["email"]
|
453
|
+
|
454
|
+
def perform
|
455
|
+
# Labels can be inspected from within the job
|
456
|
+
puts good_job_labels # => ["email"]
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
# Or add to individual jobs when enqueued
|
461
|
+
WelcomeJob.set(good_job_labels: ["email"]).perform_later
|
462
|
+
```
|
463
|
+
|
464
|
+
Labels can be used to search jobs in the Dashboard. For example, to find all jobs labeled `email`, search for `email`.
|
465
|
+
|
441
466
|
### Concurrency controls
|
442
467
|
|
443
|
-
GoodJob can extend
|
468
|
+
GoodJob can extend Active Job to provide limits on concurrently running jobs, either at time of _enqueue_ or at _perform_. Limiting concurrency can help prevent duplicate, double or unnecessary jobs from being enqueued, or race conditions when performing, for example when interacting with 3rd-party APIs.
|
444
469
|
|
445
470
|
```ruby
|
446
471
|
class MyJob < ApplicationJob
|
@@ -469,7 +494,7 @@ class MyJob < ApplicationJob
|
|
469
494
|
|
470
495
|
# A unique key to be globally locked against.
|
471
496
|
# Can be String or Lambda/Proc that is invoked in the context of the job.
|
472
|
-
# Note: Arguments passed to #perform_later can be accessed through
|
497
|
+
# Note: Arguments passed to #perform_later can be accessed through Active Job's `arguments` method
|
473
498
|
# which is an array containing positional arguments and, optionally, a kwarg hash.
|
474
499
|
key: -> { "MyJob-#{arguments.first}-#{arguments.last[:version]}" } # MyJob.perform_later("Alice", version: 'v2') => "MyJob-Alice-v2"
|
475
500
|
)
|
@@ -549,11 +574,11 @@ active_jobs = GoodJob::Bulk.enqueue do
|
|
549
574
|
# If an exception is raised within this block, no jobs will be inserted.
|
550
575
|
end
|
551
576
|
|
552
|
-
# All
|
577
|
+
# All Active Job instances are returned from GoodJob::Bulk.enqueue.
|
553
578
|
# Jobs that have been successfully enqueued have a `provider_job_id` set.
|
554
579
|
active_jobs.all?(&:provider_job_id)
|
555
580
|
|
556
|
-
# Bulk enqueue
|
581
|
+
# Bulk enqueue Active Job instances directly without using `.perform_later`:
|
557
582
|
GoodJob::Bulk.enqueue(MyJob.new, AnotherJob.new)
|
558
583
|
```
|
559
584
|
|
@@ -737,7 +762,7 @@ GoodJob follows semantic versioning, though updates may be encouraged through de
|
|
737
762
|
|
738
763
|
Upgrading between minor versions (e.g. v1.4 to v1.5) should not introduce breaking changes, but can introduce new deprecation warnings and database migration warnings.
|
739
764
|
|
740
|
-
Database migrations introduced in minor releases are _not required_ to be applied until the next major release. If you would like apply newly introduced migrations immediately, assert `GoodJob.migrated?` in your application's test suite.
|
765
|
+
Database migrations introduced in minor releases are _not required_ to be applied until the next major release. If you would like to apply newly introduced migrations immediately, assert `GoodJob.migrated?` in your application's test suite.
|
741
766
|
|
742
767
|
To perform upgrades to the GoodJob database tables:
|
743
768
|
|
@@ -791,7 +816,7 @@ Notable changes:
|
|
791
816
|
- Renames `:async_server` execution mode to `:async`; renames prior `:async` execution mode to `:async_all`.
|
792
817
|
- Sets default Development environment's execution mode to `:async` with disabled polling.
|
793
818
|
- Excludes performing jobs from `enqueue_limit`'s count in `GoodJob::ActiveJobExtensions::Concurrency`.
|
794
|
-
- Triggers `GoodJob.on_thread_error` for unhandled
|
819
|
+
- Triggers `GoodJob.on_thread_error` for unhandled Active Job exceptions.
|
795
820
|
- Renames `GoodJob.reperform_jobs_on_standard_error` accessor to `GoodJob.retry_on_unhandled_error`.
|
796
821
|
- Renames `GoodJob::Adapter.shutdown(wait:)` argument to `GoodJob::Adapter.shutdown(timeout:)`.
|
797
822
|
- Changes Advisory Lock key format from `good_jobs[ROW_ID]` to `good_jobs-[ACTIVE_JOB_ID]`.
|
@@ -801,11 +826,11 @@ Notable changes:
|
|
801
826
|
|
802
827
|
### Exceptions, retries, and reliability
|
803
828
|
|
804
|
-
GoodJob guarantees that a completely-performed job will run once and only once. GoodJob fully supports
|
829
|
+
GoodJob guarantees that a completely-performed job will run once and only once. GoodJob fully supports Active Job's built-in functionality for error handling, retries and timeouts.
|
805
830
|
|
806
831
|
#### Exceptions
|
807
832
|
|
808
|
-
|
833
|
+
Active Job provides [tools for rescuing and retrying exceptions](https://guides.rubyonrails.org/active_job_basics.html#exceptions), including `retry_on`, `discard_on`, `rescue_from` that will rescue exceptions before they get to GoodJob.
|
809
834
|
|
810
835
|
If errors do reach GoodJob, you can assign a callable to `GoodJob.on_thread_error` to be notified. For example, to log errors to an exception monitoring service like Sentry (or Bugsnag, Airbrake, Honeybadger, etc.):
|
811
836
|
|
@@ -816,9 +841,9 @@ GoodJob.on_thread_error = -> (exception) { Rails.error.report(exception) }
|
|
816
841
|
|
817
842
|
#### Retries
|
818
843
|
|
819
|
-
By default, GoodJob relies on
|
844
|
+
By default, GoodJob relies on Active Job's retry functionality.
|
820
845
|
|
821
|
-
|
846
|
+
Active Job can be configured to retry an infinite number of times, with a polynomial backoff. Using Active Job's `retry_on` prevents exceptions from reaching GoodJob:
|
822
847
|
|
823
848
|
```ruby
|
824
849
|
class ApplicationJob < ActiveJob::Base
|
@@ -860,7 +885,7 @@ end
|
|
860
885
|
|
861
886
|
By default, jobs will not be retried unless `retry_on` is configured. This can be overridden by setting `GoodJob.retry_on_unhandled_error` to `true`; GoodJob will then retry the failing job immediately and infinitely, potentially causing high load.
|
862
887
|
|
863
|
-
####
|
888
|
+
#### Action Mailer retries
|
864
889
|
|
865
890
|
Any configuration in `ApplicationJob` will have to be duplicated on `ActionMailer::MailDeliveryJob` because ActionMailer uses that custom class which inherits from `ActiveJob::Base`, rather than your application's `ApplicationJob`.
|
866
891
|
|
@@ -886,16 +911,16 @@ might also be configured to use (deprecated now) `ActionMailer::DeliveryJob`.
|
|
886
911
|
|
887
912
|
Jobs will be automatically retried if the process is interrupted while performing a job, for example as the result of a `SIGKILL` or power failure.
|
888
913
|
|
889
|
-
If you need more control over interrupt-caused retries, include the `GoodJob::ActiveJobExtensions::InterruptErrors` extension in your job class. When an interrupted job is retried, the extension will raise a `GoodJob::InterruptError` exception within the job, which allows you to use
|
914
|
+
If you need more control over interrupt-caused retries, include the `GoodJob::ActiveJobExtensions::InterruptErrors` extension in your job class. When an interrupted job is retried, the extension will raise a `GoodJob::InterruptError` exception within the job, which allows you to use Active Job's `retry_on` and `discard_on` to control the behavior of the job.
|
890
915
|
|
891
916
|
```ruby
|
892
917
|
class MyJob < ApplicationJob
|
893
918
|
# The extension must be included before other extensions
|
894
919
|
include GoodJob::ActiveJobExtensions::InterruptErrors
|
895
920
|
# Discard the job if it is interrupted
|
896
|
-
discard_on InterruptError
|
921
|
+
discard_on GoodJob::InterruptError
|
897
922
|
# Retry the job if it is interrupted
|
898
|
-
retry_on InterruptError, wait: 0, attempts: Float::INFINITY
|
923
|
+
retry_on GoodJob::InterruptError, wait: 0, attempts: Float::INFINITY
|
899
924
|
end
|
900
925
|
```
|
901
926
|
|
@@ -1176,9 +1201,9 @@ Depending on your application configuration, you may need to take additional ste
|
|
1176
1201
|
|
1177
1202
|
If you are using cron-style jobs, you might also want to look at your Passenger configuration, especially at [`passenger_pool_idle_time`](https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_pool_idle_time) and [`passenger_min_instances`](https://www.phusionpassenger.com/library/config/nginx/reference/#passenger_min_instances) to make sure there's always at least once process running that can execute cron-style scheduled jobs. See also [Passenger's optimization guide](https://www.phusionpassenger.com/library/config/nginx/optimization/#minimizing-process-spawning) for more information.
|
1178
1203
|
|
1179
|
-
### Migrate to GoodJob from a different
|
1204
|
+
### Migrate to GoodJob from a different Active Job backend
|
1180
1205
|
|
1181
|
-
If your application is already using an
|
1206
|
+
If your application is already using an Active Job backend, you will need to install GoodJob to enqueue and perform newly created jobs _and_ finish performing pre-existing jobs on the previous backend.
|
1182
1207
|
|
1183
1208
|
1. Enqueue newly created jobs on GoodJob either entirely by setting `ActiveJob::Base.queue_adapter = :good_job` or progressively via individual job classes:
|
1184
1209
|
|
@@ -1198,7 +1223,7 @@ If your application is already using an ActiveJob backend, you will need to inst
|
|
1198
1223
|
worker: bundle exec que ./config/environment.rb & bundle exec good_job & wait -n
|
1199
1224
|
```
|
1200
1225
|
|
1201
|
-
1. Once you are confident that no unperformed jobs remain in the previous
|
1226
|
+
1. Once you are confident that no unperformed jobs remain in the previous Active Job backend, code and configuration for that backend can be completely removed.
|
1202
1227
|
|
1203
1228
|
### Monitor and preserve worked jobs
|
1204
1229
|
|
@@ -1271,7 +1296,7 @@ A workaround to this limitation is to make a direct database connection availabl
|
|
1271
1296
|
url: postgres://database_host/my_database
|
1272
1297
|
```
|
1273
1298
|
|
1274
|
-
1. Create a new
|
1299
|
+
1. Create a new Active Record base class that uses the direct database connection
|
1275
1300
|
|
1276
1301
|
```ruby
|
1277
1302
|
# app/models/application_direct_record.rb
|
@@ -1282,7 +1307,7 @@ A workaround to this limitation is to make a direct database connection availabl
|
|
1282
1307
|
end
|
1283
1308
|
```
|
1284
1309
|
|
1285
|
-
1. Configure GoodJob to use the newly created
|
1310
|
+
1. Configure GoodJob to use the newly created Active Record base class:
|
1286
1311
|
|
1287
1312
|
```ruby
|
1288
1313
|
# config/initializers/good_job.rb
|
@@ -96,7 +96,7 @@ module GoodJob
|
|
96
96
|
def redirect_on_error(exception)
|
97
97
|
alert = case exception
|
98
98
|
when GoodJob::Job::AdapterNotGoodJobError
|
99
|
-
"
|
99
|
+
"Active Job Queue Adapter must be GoodJob."
|
100
100
|
when GoodJob::Job::ActionForStateMismatchError
|
101
101
|
"Job is not in an appropriate state for this action."
|
102
102
|
else
|
@@ -34,7 +34,7 @@ module GoodJob
|
|
34
34
|
query = query.to_s.strip
|
35
35
|
next if query.blank?
|
36
36
|
|
37
|
-
tsvector = "(to_tsvector('english',
|
37
|
+
tsvector = "(to_tsvector('english', id::text) || to_tsvector('english', COALESCE(active_job_id::text, '')) || to_tsvector('english', serialized_params) || to_tsvector('english', COALESCE(error, ''))#{" || to_tsvector('english', COALESCE(array_to_string(labels, ' '), ''))" if labels_migrated?})"
|
38
38
|
to_tsquery_function = database_supports_websearch_to_tsquery? ? 'websearch_to_tsquery' : 'plainto_tsquery'
|
39
39
|
where("#{tsvector} @@ #{to_tsquery_function}(?)", query)
|
40
40
|
.order(sanitize_sql_for_order([Arel.sql("ts_rank(#{tsvector}, #{to_tsquery_function}(?))"), query]) => 'DESC')
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module GoodJob
|
4
|
-
#
|
4
|
+
# Active Record 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
7
|
include AdvisoryLockable
|
@@ -56,6 +56,27 @@ module GoodJob
|
|
56
56
|
migration_pending_warning!
|
57
57
|
false
|
58
58
|
end
|
59
|
+
|
60
|
+
def labels_migrated?
|
61
|
+
return true if columns_hash["labels"].present?
|
62
|
+
|
63
|
+
migration_pending_warning!
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def labels_indices_migrated?
|
68
|
+
return true if connection.index_name_exists?(:good_jobs, :index_good_jobs_on_labels)
|
69
|
+
|
70
|
+
migration_pending_warning!
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
def active_job_id_index_removal_migrated?
|
75
|
+
return true unless connection.index_name_exists?(:good_jobs, :index_good_jobs_on_active_job_id)
|
76
|
+
|
77
|
+
migration_pending_warning!
|
78
|
+
false
|
79
|
+
end
|
59
80
|
end
|
60
81
|
|
61
82
|
# The ActiveJob job class, as a string
|
@@ -88,6 +109,7 @@ module GoodJob
|
|
88
109
|
.tap do |job_data|
|
89
110
|
job_data["provider_job_id"] = id
|
90
111
|
job_data["good_job_concurrency_key"] = concurrency_key if concurrency_key
|
112
|
+
job_data["good_job_labels"] = Array(labels) if self.class.labels_migrated? && labels.present?
|
91
113
|
end
|
92
114
|
end
|
93
115
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module GoodJob
|
4
|
-
#
|
4
|
+
# Active Record model that represents an +ActiveJob+ job.
|
5
5
|
class Execution < BaseExecution
|
6
6
|
# Raised if something attempts to execute a previously completed Execution again.
|
7
7
|
PreviouslyPerformedError = Class.new(StandardError)
|
@@ -150,9 +150,9 @@ module GoodJob
|
|
150
150
|
# @return [ActiveRecord::Relation]
|
151
151
|
scope :schedule_ordered, -> { order(coalesce_scheduled_at_created_at.asc) }
|
152
152
|
|
153
|
-
# Get
|
154
|
-
# provided, get all jobs
|
155
|
-
# destroys jobs after they
|
153
|
+
# Get completed jobs before the given timestamp. If no timestamp is
|
154
|
+
# provided, get *all* completed jobs. By default, GoodJob
|
155
|
+
# destroys jobs after they're completed, meaning this returns no jobs.
|
156
156
|
# However, if you have changed {GoodJob.preserve_job_records}, this may
|
157
157
|
# find completed Jobs.
|
158
158
|
# @!method finished(timestamp = nil)
|
@@ -225,6 +225,13 @@ module GoodJob
|
|
225
225
|
execution_args[:scheduled_at] = Time.zone.at(active_job.scheduled_at) if active_job.scheduled_at
|
226
226
|
execution_args[:concurrency_key] = active_job.good_job_concurrency_key if active_job.respond_to?(:good_job_concurrency_key)
|
227
227
|
|
228
|
+
if active_job.respond_to?(:good_job_labels) && active_job.good_job_labels.any? && labels_migrated?
|
229
|
+
labels = active_job.good_job_labels.dup
|
230
|
+
labels.map! { |label| label.to_s.strip.presence }
|
231
|
+
labels.tap(&:compact!).tap(&:uniq!)
|
232
|
+
execution_args[:labels] = labels
|
233
|
+
end
|
234
|
+
|
228
235
|
reenqueued_current_execution = CurrentThread.active_job_id && CurrentThread.active_job_id == active_job.job_id
|
229
236
|
current_execution = CurrentThread.execution
|
230
237
|
|
data/app/models/good_job/job.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module GoodJob
|
4
|
-
#
|
4
|
+
# Active Record model that represents an +ActiveJob+ job.
|
5
5
|
# There is not a table in the database whose discrete rows represents "Jobs".
|
6
6
|
# The +good_jobs+ table is a table of individual {GoodJob::Execution}s that share the same +active_job_id+.
|
7
7
|
# A single row from the +good_jobs+ table of executions is fetched to represent a Job.
|
@@ -9,7 +9,7 @@ module GoodJob
|
|
9
9
|
class Job < BaseExecution
|
10
10
|
# Raised when an inappropriate action is applied to a Job based on its state.
|
11
11
|
ActionForStateMismatchError = Class.new(StandardError)
|
12
|
-
# Raised when
|
12
|
+
# Raised when GoodJob is not configured as the Active Job Queue Adapter
|
13
13
|
AdapterNotGoodJobError = Class.new(StandardError)
|
14
14
|
# Attached to a Job's Execution when the Job is discarded.
|
15
15
|
DiscardJobError = Class.new(StandardError)
|
@@ -60,7 +60,7 @@ module GoodJob
|
|
60
60
|
|
61
61
|
scope :unfinished_undiscrete, -> { where(finished_at: nil, retried_good_job_id: nil, is_discrete: [nil, false]) }
|
62
62
|
|
63
|
-
# The job's
|
63
|
+
# The job's Active Job UUID
|
64
64
|
# @return [String]
|
65
65
|
def id
|
66
66
|
active_job_id
|
@@ -101,7 +101,7 @@ module GoodJob
|
|
101
101
|
executions.first
|
102
102
|
end
|
103
103
|
|
104
|
-
# The number of times this job has been executed, according to
|
104
|
+
# The number of times this job has been executed, according to Active Job's serialized state.
|
105
105
|
# @return [Numeric]
|
106
106
|
def executions_count
|
107
107
|
aj_count = serialized_params.fetch('executions', 0)
|
@@ -1,13 +1,5 @@
|
|
1
1
|
<footer class="footer mt-auto py-3 bg-body-tertiary border-top text-muted small" id="footer" data-live-poll-region="footer">
|
2
2
|
<div class="container-fluid">
|
3
|
-
|
4
|
-
<div class="col-6">
|
5
|
-
<%= t(".last_update_html", time: Time.current.utc.iso8601) %>
|
6
|
-
</div>
|
7
|
-
|
8
|
-
<div class="col-6 text-end">
|
9
|
-
<%= t(".wording") %>
|
10
|
-
</div>
|
11
|
-
</div>
|
3
|
+
GoodJob v<%= GoodJob::VERSION %>
|
12
4
|
</div>
|
13
5
|
</footer>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<nav class="navbar navbar-expand-lg border-bottom bg-body sticky-top
|
1
|
+
<nav class="navbar navbar-expand-lg border-bottom bg-body sticky-top">
|
2
2
|
<div class="container-fluid">
|
3
3
|
<%= link_to t(".name"), root_path, class: "navbar-brand mb-0 h1" %>
|
4
4
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<nav class="navbar p-1 shadow-sm mt-auto border-bottom text-muted small" id="secondary-navbar" data-live-poll-region="secondary-navbar">
|
2
|
+
<div class="container-fluid">
|
3
|
+
<div class="flex-fill d-none d-sm-block ">
|
4
|
+
<%= t(".inspiration") %>
|
5
|
+
</div>
|
6
|
+
<div class="flex-fill text-end">
|
7
|
+
<% last_updated_at = Time.current.utc.iso8601 %>
|
8
|
+
<%= t(".last_updated") %> <time id="page-updated-at" datetime="<%= last_updated_at %>"><%== last_updated_at %></time>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
</nav>
|
@@ -1,44 +1,39 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html lang="<%= I18n.locale %>" data-bs-theme="auto">
|
3
|
-
<head>
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
// Ensure theme is updated before dom loads to avoid flash of style
|
24
|
-
let theme = localStorage.getItem('good_job-theme');
|
25
|
-
if (!["light", "dark"].includes(theme)) {
|
3
|
+
<head>
|
4
|
+
<title>Good Job Dashboard</title>
|
5
|
+
<meta charset="utf-8">
|
6
|
+
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
<%= csp_meta_tag %>
|
9
|
+
<%# Do not use asset tag helpers to avoid paths being overriden by config.asset_host %>
|
10
|
+
<%= tag.link rel: "stylesheet", href: frontend_static_path(:bootstrap, format: :css, v: GoodJob::VERSION, locale: nil), nonce: content_security_policy_nonce %>
|
11
|
+
<%= tag.link rel: "stylesheet", href: frontend_static_path(:style, format: :css, v: GoodJob::VERSION, locale: nil), nonce: content_security_policy_nonce %>
|
12
|
+
<%= tag.script "", src: frontend_static_path(:bootstrap, format: :js, v: GoodJob::VERSION, locale: nil), nonce: content_security_policy_nonce %>
|
13
|
+
<%= tag.script "", src: frontend_static_path(:chartjs, format: :js, v: GoodJob::VERSION, locale: nil), nonce: content_security_policy_nonce %>
|
14
|
+
<%= tag.script "", src: frontend_static_path(:rails_ujs, format: :js, v: GoodJob::VERSION, locale: nil), nonce: content_security_policy_nonce %>
|
15
|
+
<%= tag.script "", src: frontend_static_path(:es_module_shims, format: :js, v: GoodJob::VERSION, locale: nil), async: true, nonce: content_security_policy_nonce %>
|
16
|
+
<% importmaps = GoodJob::FrontendsController.js_modules.keys.index_with { |module_name| frontend_module_path(module_name, format: :js, locale: nil, v: GoodJob::VERSION) } %>
|
17
|
+
<%= tag.script({ imports: importmaps }.to_json.html_safe, type: "importmap", nonce: content_security_policy_nonce) %>
|
18
|
+
<%= tag.script "", type: "module", nonce: content_security_policy_nonce do %> import "application"; <% end %>
|
19
|
+
<%= tag.script "", nonce: content_security_policy_nonce do %>
|
20
|
+
// Ensure theme is updated before dom loads to avoid flash of style
|
21
|
+
let theme = localStorage.getItem('good_job-theme');
|
22
|
+
if (!["light", "dark"].includes(theme)) {
|
26
23
|
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
</head>
|
31
|
-
<body>
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
24
|
+
}
|
25
|
+
document.documentElement.setAttribute('data-bs-theme', theme);
|
26
|
+
<% end %>
|
27
|
+
</head>
|
28
|
+
<body>
|
29
|
+
<div class="d-flex flex-column min-vh-100">
|
30
|
+
<%= render "good_job/shared/navbar" %>
|
31
|
+
<%= render "good_job/shared/secondary_navbar" %>
|
32
|
+
<div class="container-fluid flex-grow-1 relative">
|
33
|
+
<%= render "good_job/shared/alert" %>
|
34
|
+
<%= yield %>
|
35
|
+
</div>
|
36
|
+
<%= render "good_job/shared/footer" %>
|
39
37
|
</div>
|
40
|
-
|
41
|
-
<%= render "good_job/shared/footer" %>
|
42
|
-
</div>
|
43
|
-
</body>
|
38
|
+
</body>
|
44
39
|
</html>
|
data/config/locales/de.yml
CHANGED
@@ -219,9 +219,6 @@ de:
|
|
219
219
|
placeholder: Suchen Sie nach Klasse, Job-ID, Jobparametern und Fehlertext.
|
220
220
|
queue_name: Warteschlangenname
|
221
221
|
search: Suchen
|
222
|
-
footer:
|
223
|
-
last_update_html: Zuletzt aktualisiert <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
224
|
-
wording: Denk daran, auch du machst einen guten Job!
|
225
222
|
navbar:
|
226
223
|
batches: Batches
|
227
224
|
cron_schedules: Cron
|
@@ -234,6 +231,9 @@ de:
|
|
234
231
|
dark: Dunkel
|
235
232
|
light: Licht
|
236
233
|
theme: Thema
|
234
|
+
secondary_navbar:
|
235
|
+
inspiration: Denk daran, auch du machst einen guten Job!
|
236
|
+
last_updated: Zuletzt aktualisiert
|
237
237
|
status:
|
238
238
|
discarded: Ausrangiert
|
239
239
|
queued: In der Warteschlange
|
data/config/locales/en.yml
CHANGED
@@ -219,9 +219,6 @@ en:
|
|
219
219
|
placeholder: Search by class, job id, job params, and error text.
|
220
220
|
queue_name: Queue name
|
221
221
|
search: Search
|
222
|
-
footer:
|
223
|
-
last_update_html: Last updated <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
224
|
-
wording: Remember, you're doing a Good Job too!
|
225
222
|
navbar:
|
226
223
|
batches: Batches
|
227
224
|
cron_schedules: Cron
|
@@ -234,6 +231,9 @@ en:
|
|
234
231
|
dark: Dark
|
235
232
|
light: Light
|
236
233
|
theme: Theme
|
234
|
+
secondary_navbar:
|
235
|
+
inspiration: Remember, you're doing a Good Job too!
|
236
|
+
last_updated: Last updated
|
237
237
|
status:
|
238
238
|
discarded: Discarded
|
239
239
|
queued: Queued
|
data/config/locales/es.yml
CHANGED
@@ -217,9 +217,6 @@ es:
|
|
217
217
|
placeholder: Buscar por clase, id de tarea, parámetros y mensaje de error.
|
218
218
|
queue_name: Nombre de la cola
|
219
219
|
search: Buscar
|
220
|
-
footer:
|
221
|
-
last_update_html: Última actualización <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
222
|
-
wording: "¡Recuerda, también tú estás haciendo un buen trabajo!"
|
223
220
|
navbar:
|
224
221
|
batches: Batches
|
225
222
|
cron_schedules: Cron
|
@@ -232,6 +229,9 @@ es:
|
|
232
229
|
dark: Oscuro
|
233
230
|
light: Luz
|
234
231
|
theme: Tema
|
232
|
+
secondary_navbar:
|
233
|
+
inspiration: "¡Recuerda, también tú estás haciendo un buen trabajo!"
|
234
|
+
last_updated: Última actualización
|
235
235
|
status:
|
236
236
|
discarded:
|
237
237
|
one: Descartada
|
data/config/locales/fr.yml
CHANGED
@@ -219,9 +219,6 @@ fr:
|
|
219
219
|
placeholder: Recherche par classe, ID de job, paramètres de job et texte d'erreur.
|
220
220
|
queue_name: Nom de la file d'attente
|
221
221
|
search: Recherche
|
222
|
-
footer:
|
223
|
-
last_update_html: Dernière mise à jour <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
224
|
-
wording: N'oublie pas, toi aussi tu fais du bon boulot !
|
225
222
|
navbar:
|
226
223
|
batches: Lots
|
227
224
|
cron_schedules: Cron
|
@@ -234,6 +231,9 @@ fr:
|
|
234
231
|
dark: Sombre
|
235
232
|
light: Lumière
|
236
233
|
theme: Thème
|
234
|
+
secondary_navbar:
|
235
|
+
inspiration: N'oublie pas, toi aussi tu fais du bon boulot !
|
236
|
+
last_updated: Dernière mise à jour
|
237
237
|
status:
|
238
238
|
discarded: Mis au rebut
|
239
239
|
queued: À la file
|
data/config/locales/ja.yml
CHANGED
@@ -219,9 +219,6 @@ ja:
|
|
219
219
|
placeholder: クラス名、ジョブID、ジョブパラメータ、エラーテキストで検索
|
220
220
|
queue_name: キュー名
|
221
221
|
search: 検索
|
222
|
-
footer:
|
223
|
-
last_update_html: 最終更新 <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
224
|
-
wording: Remember, you're doing a Good Job too!
|
225
222
|
navbar:
|
226
223
|
batches: バッチ
|
227
224
|
cron_schedules: Cron
|
@@ -234,6 +231,9 @@ ja:
|
|
234
231
|
dark: 暗い
|
235
232
|
light: ライト
|
236
233
|
theme: テーマ
|
234
|
+
secondary_navbar:
|
235
|
+
inspiration: 覚えておいてください、あなたも良い仕事をしています!
|
236
|
+
last_updated: 最終更新
|
237
237
|
status:
|
238
238
|
discarded: 破棄済み
|
239
239
|
queued: 処理待ち
|
data/config/locales/nl.yml
CHANGED
@@ -219,9 +219,6 @@ nl:
|
|
219
219
|
placeholder: Zoek op klasse, taak-ID, taakparameters en fouttekst.
|
220
220
|
queue_name: Wachtrij naam
|
221
221
|
search: Zoekopdracht
|
222
|
-
footer:
|
223
|
-
last_update_html: Laatst bijgewerkt <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
224
|
-
wording: 'Onthoud: jij levert ook goed werk!'
|
225
222
|
navbar:
|
226
223
|
batches: Batches
|
227
224
|
cron_schedules: Cron
|
@@ -234,6 +231,9 @@ nl:
|
|
234
231
|
dark: Donker
|
235
232
|
light: Licht
|
236
233
|
theme: Thema
|
234
|
+
secondary_navbar:
|
235
|
+
inspiration: 'Onthoud: jij levert ook goed werk!'
|
236
|
+
last_updated: Laatst bijgewerkt
|
237
237
|
status:
|
238
238
|
discarded: weggegooid
|
239
239
|
queued: In de wachtrij
|
data/config/locales/ru.yml
CHANGED
@@ -245,9 +245,6 @@ ru:
|
|
245
245
|
placeholder: Поиск по классу, идентификатору задания, параметрам задания и тексту ошибки.
|
246
246
|
queue_name: Имя очереди
|
247
247
|
search: Поиск
|
248
|
-
footer:
|
249
|
-
last_update_html: Последнее обновление <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
250
|
-
wording: Запомни, ты делаешь Good Job тоже!
|
251
248
|
navbar:
|
252
249
|
batches: Batches
|
253
250
|
cron_schedules: Cron
|
@@ -260,6 +257,9 @@ ru:
|
|
260
257
|
dark: Темный
|
261
258
|
light: Свет
|
262
259
|
theme: Тема
|
260
|
+
secondary_navbar:
|
261
|
+
inspiration: Запомни, ты делаешь Good Job тоже!
|
262
|
+
last_updated: Последнее обновление
|
263
263
|
status:
|
264
264
|
discarded: Отброшено
|
265
265
|
queued: В очереди
|
data/config/locales/tr.yml
CHANGED
@@ -219,9 +219,6 @@ tr:
|
|
219
219
|
placeholder: Sınıfa, iş kimliğine, iş parametrelerine ve hata metnine göre ara.
|
220
220
|
queue_name: Kuyruk adı
|
221
221
|
search: Ara
|
222
|
-
footer:
|
223
|
-
last_update_html: Son güncelleme <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
224
|
-
wording: Unutmayın, siz de iyi bir iş yapıyorsunuz!
|
225
222
|
navbar:
|
226
223
|
batches: Toplu İşler
|
227
224
|
cron_schedules: Cron
|
@@ -234,6 +231,9 @@ tr:
|
|
234
231
|
dark: Karanlık
|
235
232
|
light: Işık
|
236
233
|
theme: Tema
|
234
|
+
secondary_navbar:
|
235
|
+
inspiration: Unutmayın, siz de iyi bir iş yapıyorsunuz!
|
236
|
+
last_updated: Son güncelleme
|
237
237
|
status:
|
238
238
|
discarded: İptal Edildi
|
239
239
|
queued: Sırada
|
data/config/locales/uk.yml
CHANGED
@@ -245,9 +245,6 @@ uk:
|
|
245
245
|
placeholder: Пошук за класом, ідентифікатором роботи, параметрами роботи та текстом помилки.
|
246
246
|
queue_name: Назва черги
|
247
247
|
search: Пошук
|
248
|
-
footer:
|
249
|
-
last_update_html: Останнє оновлення <time id="page-updated-at" datetime="%{time}">%{time}</time>
|
250
|
-
wording: Пам'ятайте, ви теж робите хорошу роботу!
|
251
248
|
navbar:
|
252
249
|
batches: Batches
|
253
250
|
cron_schedules: Cron
|
@@ -260,6 +257,9 @@ uk:
|
|
260
257
|
dark: Темний
|
261
258
|
light: світло
|
262
259
|
theme: Тема
|
260
|
+
secondary_navbar:
|
261
|
+
inspiration: Пам'ятайте, ви теж робите хорошу роботу!
|
262
|
+
last_updated: Останнє оновлення
|
263
263
|
status:
|
264
264
|
discarded: Відхилено
|
265
265
|
queued: У черзі
|
@@ -29,6 +29,7 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
|
29
29
|
t.integer :executions_count
|
30
30
|
t.text :job_class
|
31
31
|
t.integer :error_event, limit: 2
|
32
|
+
t.text :labels, array: true
|
32
33
|
end
|
33
34
|
|
34
35
|
create_table :good_job_batches, id: :uuid do |t|
|
@@ -76,12 +77,12 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
|
76
77
|
add_index :good_jobs, :concurrency_key, where: "(finished_at IS NULL)", name: :index_good_jobs_on_concurrency_key_when_unfinished
|
77
78
|
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
|
78
79
|
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
|
79
|
-
add_index :good_jobs, [:active_job_id], name: :index_good_jobs_on_active_job_id
|
80
80
|
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
|
81
81
|
add_index :good_jobs, [:priority, :created_at], order: { priority: "DESC NULLS LAST", created_at: :asc },
|
82
82
|
where: "finished_at IS NULL", name: :index_good_jobs_jobs_on_priority_created_at_when_unfinished
|
83
83
|
add_index :good_jobs, [:batch_id], where: "batch_id IS NOT NULL"
|
84
84
|
add_index :good_jobs, [:batch_callback_id], where: "batch_callback_id IS NOT NULL"
|
85
|
+
add_index :good_jobs, :labels, using: :gin, where: "(labels IS NOT NULL)", name: :index_good_jobs_on_labels
|
85
86
|
|
86
87
|
add_index :good_job_executions, [:active_job_id, :created_at], name: :index_good_job_executions_on_active_job_id_and_created_at
|
87
88
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateGoodJobLabels < 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, :labels)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
add_column :good_jobs, :labels, :text, array: true
|
14
|
+
end
|
15
|
+
end
|
data/lib/generators/good_job/templates/update/migrations/09_create_good_job_labels_index.rb.erb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateGoodJobLabelsIndex < ActiveRecord::Migration<%= migration_version %>
|
4
|
+
disable_ddl_transaction!
|
5
|
+
|
6
|
+
def change
|
7
|
+
reversible do |dir|
|
8
|
+
dir.up do
|
9
|
+
unless connection.index_name_exists?(:good_jobs, :index_good_jobs_on_labels)
|
10
|
+
add_index :good_jobs, :labels, using: :gin, where: "(labels IS NOT NULL)",
|
11
|
+
name: :index_good_jobs_on_labels, algorithm: :concurrently
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
dir.down do
|
16
|
+
if connection.index_name_exists?(:good_jobs, :index_good_jobs_on_labels)
|
17
|
+
remove_index :good_jobs, name: :index_good_jobs_on_labels
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/generators/good_job/templates/update/migrations/10_remove_good_job_active_id_index.rb.erb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RemoveGoodJobActiveIdIndex < ActiveRecord::Migration<%= migration_version %>
|
4
|
+
disable_ddl_transaction!
|
5
|
+
|
6
|
+
def change
|
7
|
+
reversible do |dir|
|
8
|
+
dir.up do
|
9
|
+
if connection.index_name_exists?(:good_jobs, :index_good_jobs_on_active_job_id)
|
10
|
+
remove_index :good_jobs, name: :index_good_jobs_on_active_job_id
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
dir.down do
|
15
|
+
unless connection.index_name_exists?(:good_jobs, :index_good_jobs_on_active_job_id)
|
16
|
+
add_index :good_jobs, :active_job_id, name: :index_good_jobs_on_active_job_id
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GoodJob
|
4
|
+
module ActiveJobExtensions
|
5
|
+
module Labels
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module Prepends
|
9
|
+
def initialize(*arguments)
|
10
|
+
super
|
11
|
+
self.good_job_labels = Array(self.class.good_job_labels)
|
12
|
+
end
|
13
|
+
|
14
|
+
def enqueue(options = {})
|
15
|
+
self.good_job_labels = Array(options[:good_job_labels]) if options.key?(:good_job_labels)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def deserialize(job_data)
|
20
|
+
super
|
21
|
+
self.good_job_labels = job_data.delete("good_job_labels")&.dup || []
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
included do
|
26
|
+
prepend Prepends
|
27
|
+
class_attribute :good_job_labels, instance_accessor: false, instance_predicate: false, default: []
|
28
|
+
attr_accessor :good_job_labels
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/good_job/version.rb
CHANGED
data/lib/good_job.rb
CHANGED
@@ -12,6 +12,7 @@ require "good_job/active_job_extensions/batches"
|
|
12
12
|
require "good_job/active_job_extensions/concurrency"
|
13
13
|
require "good_job/interrupt_error"
|
14
14
|
require "good_job/active_job_extensions/interrupt_errors"
|
15
|
+
require "good_job/active_job_extensions/labels"
|
15
16
|
require "good_job/active_job_extensions/notify_options"
|
16
17
|
|
17
18
|
require "good_job/assignable_connection"
|
@@ -22,7 +23,7 @@ require "good_job/cleanup_tracker"
|
|
22
23
|
require "good_job/cli"
|
23
24
|
require "good_job/configuration"
|
24
25
|
require "good_job/cron_manager"
|
25
|
-
require
|
26
|
+
require "good_job/current_thread"
|
26
27
|
require "good_job/daemon"
|
27
28
|
require "good_job/dependencies"
|
28
29
|
require "good_job/job_performer"
|
@@ -272,7 +273,7 @@ module GoodJob
|
|
272
273
|
def self.migrated?
|
273
274
|
# Always update with the most recent migration check
|
274
275
|
GoodJob::Execution.reset_column_information
|
275
|
-
GoodJob::Execution.
|
276
|
+
GoodJob::Execution.active_job_id_index_removal_migrated?
|
276
277
|
end
|
277
278
|
|
278
279
|
ActiveSupport.run_load_hooks(:good_job, self)
|
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.
|
4
|
+
version: 3.22.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:
|
11
|
+
date: 2024-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -307,6 +307,7 @@ files:
|
|
307
307
|
- app/views/good_job/shared/_filter.erb
|
308
308
|
- app/views/good_job/shared/_footer.erb
|
309
309
|
- app/views/good_job/shared/_navbar.erb
|
310
|
+
- app/views/good_job/shared/_secondary_navbar.erb
|
310
311
|
- app/views/good_job/shared/icons/_arrow_clockwise.html.erb
|
311
312
|
- app/views/good_job/shared/icons/_check.html.erb
|
312
313
|
- app/views/good_job/shared/icons/_circle_half.html.erb
|
@@ -345,11 +346,15 @@ files:
|
|
345
346
|
- lib/generators/good_job/templates/update/migrations/05_create_good_job_executions.rb.erb
|
346
347
|
- lib/generators/good_job/templates/update/migrations/06_create_good_jobs_error_event.rb.erb
|
347
348
|
- lib/generators/good_job/templates/update/migrations/07_recreate_good_job_cron_indexes_with_conditional.rb.erb
|
349
|
+
- lib/generators/good_job/templates/update/migrations/08_create_good_job_labels.rb.erb
|
350
|
+
- lib/generators/good_job/templates/update/migrations/09_create_good_job_labels_index.rb.erb
|
351
|
+
- lib/generators/good_job/templates/update/migrations/10_remove_good_job_active_id_index.rb.erb
|
348
352
|
- lib/generators/good_job/update_generator.rb
|
349
353
|
- lib/good_job.rb
|
350
354
|
- lib/good_job/active_job_extensions/batches.rb
|
351
355
|
- lib/good_job/active_job_extensions/concurrency.rb
|
352
356
|
- lib/good_job/active_job_extensions/interrupt_errors.rb
|
357
|
+
- lib/good_job/active_job_extensions/labels.rb
|
353
358
|
- lib/good_job/active_job_extensions/notify_options.rb
|
354
359
|
- lib/good_job/adapter.rb
|
355
360
|
- lib/good_job/assignable_connection.rb
|