good_job 1.2.1 β†’ 1.2.6

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +131 -1
  3. data/README.md +321 -160
  4. data/engine/app/controllers/good_job/active_jobs_controller.rb +8 -0
  5. data/engine/app/controllers/good_job/base_controller.rb +5 -0
  6. data/engine/app/controllers/good_job/dashboards_controller.rb +50 -0
  7. data/engine/app/helpers/good_job/application_helper.rb +4 -0
  8. data/engine/app/views/assets/_style.css.erb +16 -0
  9. data/engine/app/views/good_job/active_jobs/show.html.erb +1 -0
  10. data/engine/app/views/good_job/dashboards/index.html.erb +19 -0
  11. data/engine/app/views/layouts/good_job/base.html.erb +61 -0
  12. data/engine/app/views/shared/_chart.erb +51 -0
  13. data/engine/app/views/shared/_jobs_table.erb +26 -0
  14. data/engine/app/views/vendor/bootstrap/_bootstrap-native.js.erb +1662 -0
  15. data/engine/app/views/vendor/bootstrap/_bootstrap.css.erb +10258 -0
  16. data/engine/app/views/vendor/chartist/_chartist.css.erb +613 -0
  17. data/engine/app/views/vendor/chartist/_chartist.js.erb +4516 -0
  18. data/engine/config/routes.rb +4 -0
  19. data/engine/lib/good_job/engine.rb +5 -0
  20. data/lib/active_job/queue_adapters/good_job_adapter.rb +3 -2
  21. data/lib/generators/good_job/install_generator.rb +8 -0
  22. data/lib/good_job.rb +41 -25
  23. data/lib/good_job/adapter.rb +44 -4
  24. data/lib/good_job/cli.rb +66 -13
  25. data/lib/good_job/configuration.rb +61 -2
  26. data/lib/good_job/job.rb +128 -37
  27. data/lib/good_job/lockable.rb +125 -14
  28. data/lib/good_job/log_subscriber.rb +70 -6
  29. data/lib/good_job/multi_scheduler.rb +6 -0
  30. data/lib/good_job/notifier.rb +64 -27
  31. data/lib/good_job/performer.rb +38 -0
  32. data/lib/good_job/railtie.rb +1 -0
  33. data/lib/good_job/scheduler.rb +49 -40
  34. data/lib/good_job/version.rb +2 -1
  35. metadata +163 -7
  36. data/lib/good_job/pg_locks.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08edeaef5cda608f5e5afd0ee0c8813805e4e88791a338dc66ab9129a9f727f6'
4
- data.tar.gz: 3608a46f95035a843ea422cca420f344d870a8be558fe9f2cdb6c765c5cbd153
3
+ metadata.gz: 7bb8c33f26176b048399e596b7c4c5dcb10553209b9237fe6256e7af66b1ffcc
4
+ data.tar.gz: b401649bfe1dee5f83575e82cb2703407c2ddc367dabaabc05f41d9f79e4315d
5
5
  SHA512:
6
- metadata.gz: 57f471ffef16a4f1def70922e8601b3612de84441233523492a543b7276dbb00c5dd8e37a8fd7c58d930ac78c3ea0f65704a4bef4175ef588fbf65d11051eca7
7
- data.tar.gz: e0d76a4990f613b81431e42c89f5ff1172b5353a9025d6684d866048771cbd845d51a12a212fe1df85934d7854f298a333d426b8738b0fbfd2fbbad27880f02a
6
+ metadata.gz: d38c25e5f61a8d6509f323509ecd5e0fb49a31466b58a3eae47a5614b0e56f3b30a90725d8e57dc0d170a1cda635cb49850cc98d6b4c1c4033c8a65db691af8c
7
+ data.tar.gz: 31add663e7307890b66f89e14b5ea164c9c67252c695db50f0d761921308019fcf7874984db7f263ae67557d1538f6b25d15271ca9880190b6faf13dc29346f8
@@ -1,12 +1,142 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.2.6](https://github.com/bensheldon/good_job/tree/v1.2.6) (2020-09-29)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.5...v1.2.6)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Preserve only failed jobs [\#136](https://github.com/bensheldon/good_job/issues/136)
10
+ - Add `GoodJob.preserve\_job\_records = :on\_unhandled\_error` option to only preserve jobs that errored [\#145](https://github.com/bensheldon/good_job/pull/145) ([morgoth](https://github.com/morgoth))
11
+
12
+ **Fixed bugs:**
13
+
14
+ - Fix LogSubscriber notifications for finished\_timer\_task and finished\_job\_task [\#148](https://github.com/bensheldon/good_job/pull/148) ([bensheldon](https://github.com/bensheldon))
15
+
16
+ **Closed issues:**
17
+
18
+ - run-once guarantee? [\#151](https://github.com/bensheldon/good_job/issues/151)
19
+
20
+ **Merged pull requests:**
21
+
22
+ - Add info how to setup basic auth for engine [\#153](https://github.com/bensheldon/good_job/pull/153) ([morgoth](https://github.com/morgoth))
23
+ - Add documentation for Dashboard Rails::Engine [\#149](https://github.com/bensheldon/good_job/pull/149) ([bensheldon](https://github.com/bensheldon))
24
+ - Style cleanup to Job error handling [\#147](https://github.com/bensheldon/good_job/pull/147) ([bensheldon](https://github.com/bensheldon))
25
+ - Replace gerund titles in Readme [\#146](https://github.com/bensheldon/good_job/pull/146) ([bensheldon](https://github.com/bensheldon))
26
+ - Only allow Scheduler to be initialized with max\_threads and poll\_interval; remove full access to pool and timer\_task options [\#137](https://github.com/bensheldon/good_job/pull/137) ([bensheldon](https://github.com/bensheldon))
27
+
28
+ ## [v1.2.5](https://github.com/bensheldon/good_job/tree/v1.2.5) (2020-09-17)
29
+
30
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.4...v1.2.5)
31
+
32
+ **Implemented enhancements:**
33
+
34
+ - Use Zeitwerk for auto-loading [\#87](https://github.com/bensheldon/good_job/issues/87)
35
+ - Spike on data dashboard; pull in full Bootstrap CSS and JS [\#131](https://github.com/bensheldon/good_job/pull/131) ([bensheldon](https://github.com/bensheldon))
36
+
37
+ **Fixed bugs:**
38
+
39
+ - `poll-interval=-1` does not disable polling as intended [\#133](https://github.com/bensheldon/good_job/issues/133)
40
+ - Update Gemspec to reflect that GoodJob is not compatible with Rails 5.1 [\#143](https://github.com/bensheldon/good_job/pull/143) ([bensheldon](https://github.com/bensheldon))
41
+ - Prevent jobs hanging [\#141](https://github.com/bensheldon/good_job/pull/141) ([morgoth](https://github.com/morgoth))
42
+ - Add explicit require\_paths to gemspec for engine [\#134](https://github.com/bensheldon/good_job/pull/134) ([bensheldon](https://github.com/bensheldon))
43
+ - Use `connection.quote\_table\_name` and add spacing for SQL concatenation [\#124](https://github.com/bensheldon/good_job/pull/124) ([bensheldon](https://github.com/bensheldon))
44
+
45
+ **Closed issues:**
46
+
47
+ - Lint - Introduce line character limits [\#122](https://github.com/bensheldon/good_job/issues/122)
48
+ - Jobs are not processed in multi schema setup. Apartment + GoodJob \( post 1.1.2 \) [\#117](https://github.com/bensheldon/good_job/issues/117)
49
+ - Host a documentation sprint [\#48](https://github.com/bensheldon/good_job/issues/48)
50
+
51
+ **Merged pull requests:**
52
+
53
+ - Test GoodJob against Rails HEAD [\#144](https://github.com/bensheldon/good_job/pull/144) ([bensheldon](https://github.com/bensheldon))
54
+ - Drop Ruby 2.4 support [\#142](https://github.com/bensheldon/good_job/pull/142) ([morgoth](https://github.com/morgoth))
55
+ - Remove arguments from perform method [\#140](https://github.com/bensheldon/good_job/pull/140) ([morgoth](https://github.com/morgoth))
56
+ - Extract "execute" method to reduce "perform" method complexity [\#138](https://github.com/bensheldon/good_job/pull/138) ([morgoth](https://github.com/morgoth))
57
+ - Correct example on how to configure multiple queues by command line. [\#135](https://github.com/bensheldon/good_job/pull/135) ([morgoth](https://github.com/morgoth))
58
+ - Update ActionMailer Job class, to match the default [\#130](https://github.com/bensheldon/good_job/pull/130) ([morgoth](https://github.com/morgoth))
59
+ - Add initial Engine scaffold [\#125](https://github.com/bensheldon/good_job/pull/125) ([bensheldon](https://github.com/bensheldon))
60
+ - Zeitwerk Loader Implementation [\#123](https://github.com/bensheldon/good_job/pull/123) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
61
+ - Update code-level documentation [\#111](https://github.com/bensheldon/good_job/pull/111) ([bensheldon](https://github.com/bensheldon))
62
+
63
+ ## [v1.2.4](https://github.com/bensheldon/good_job/tree/v1.2.4) (2020-09-01)
64
+
65
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.3...v1.2.4)
66
+
67
+ **Implemented enhancements:**
68
+
69
+ - Add environment variable to mirror `cleanup\_preserved\_jobs --before-seconds-ago=SECONDS` [\#110](https://github.com/bensheldon/good_job/issues/110)
70
+ - Allow env variable config for cleanups [\#114](https://github.com/bensheldon/good_job/pull/114) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
71
+
72
+ **Fixed bugs:**
73
+
74
+ - Better table name detection for Job queries [\#119](https://github.com/bensheldon/good_job/pull/119) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
75
+
76
+ **Closed issues:**
77
+
78
+ - Remove unused PgLocks class [\#121](https://github.com/bensheldon/good_job/issues/121)
79
+ - Fix minor issue with CommandLine option links in README.md [\#116](https://github.com/bensheldon/good_job/issues/116)
80
+ - Unused .advisory\_lock\_details in PgLocks [\#105](https://github.com/bensheldon/good_job/issues/105)
81
+
82
+ **Merged pull requests:**
83
+
84
+ - Remove unused PgLocks class [\#120](https://github.com/bensheldon/good_job/pull/120) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
85
+ - Fix readme CommandLine option links [\#115](https://github.com/bensheldon/good_job/pull/115) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
86
+ - Have YARD render markdown files with GFM \(Github Flavored Markdown\) [\#113](https://github.com/bensheldon/good_job/pull/113) ([bensheldon](https://github.com/bensheldon))
87
+ - Add markdownlint to lint readme [\#109](https://github.com/bensheldon/good_job/pull/109) ([bensheldon](https://github.com/bensheldon))
88
+ - Remove unused method in PgLocks [\#107](https://github.com/bensheldon/good_job/pull/107) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
89
+ - Re-organize Readme: frontload configuration, add Table of Contents [\#106](https://github.com/bensheldon/good_job/pull/106) ([bensheldon](https://github.com/bensheldon))
90
+
91
+ ## [v1.2.3](https://github.com/bensheldon/good_job/tree/v1.2.3) (2020-08-27)
92
+
93
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.2...v1.2.3)
94
+
95
+ **Closed issues:**
96
+
97
+ - requiring more dependencies in then needed [\#103](https://github.com/bensheldon/good_job/issues/103)
98
+
99
+ **Merged pull requests:**
100
+
101
+ - stop depending on all rails libs [\#104](https://github.com/bensheldon/good_job/pull/104) ([thilo](https://github.com/thilo))
102
+
103
+ ## [v1.2.2](https://github.com/bensheldon/good_job/tree/v1.2.2) (2020-08-27)
104
+
105
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.1...v1.2.2)
106
+
107
+ **Implemented enhancements:**
108
+
109
+ - Run Github Action tests against Ruby 2.5, 2.6, 2.7 [\#100](https://github.com/bensheldon/good_job/issues/100)
110
+
111
+ **Fixed bugs:**
112
+
113
+ - Freezes puma on code change [\#95](https://github.com/bensheldon/good_job/issues/95)
114
+ - Ruby 2.7 keyword arguments warning [\#93](https://github.com/bensheldon/good_job/issues/93)
115
+
116
+ **Closed issues:**
117
+
118
+ - Add test for `rails g good\_job:install` [\#57](https://github.com/bensheldon/good_job/issues/57)
119
+
120
+ **Merged pull requests:**
121
+
122
+ - Use more ActiveRecord in Lockable and not connection.execute [\#102](https://github.com/bensheldon/good_job/pull/102) ([bensheldon](https://github.com/bensheldon))
123
+ - Run CI tests on Ruby 2.5, 2.6, and 2.7 [\#101](https://github.com/bensheldon/good_job/pull/101) ([arku](https://github.com/arku))
124
+ - Return to using executor.wrap around Scheduler execution task [\#99](https://github.com/bensheldon/good_job/pull/99) ([bensheldon](https://github.com/bensheldon))
125
+ - Fix Ruby 2.7 keyword arguments warning [\#98](https://github.com/bensheldon/good_job/pull/98) ([arku](https://github.com/arku))
126
+ - Remove executor/reloader for less interlocking [\#97](https://github.com/bensheldon/good_job/pull/97) ([sj26](https://github.com/sj26))
127
+ - Name the thread pools [\#96](https://github.com/bensheldon/good_job/pull/96) ([sj26](https://github.com/sj26))
128
+ - Add test for `rails g good\_job:install` [\#94](https://github.com/bensheldon/good_job/pull/94) ([arku](https://github.com/arku))
129
+
3
130
  ## [v1.2.1](https://github.com/bensheldon/good_job/tree/v1.2.1) (2020-08-21)
4
131
 
5
132
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.0...v1.2.1)
6
133
 
7
- **Closed issues:**
134
+ **Fixed bugs:**
8
135
 
9
136
  - undefined method `thread\_mattr\_accessor' when not requiring the Sprockets Railstie [\#85](https://github.com/bensheldon/good_job/issues/85)
137
+
138
+ **Closed issues:**
139
+
10
140
  - Document comparison of GoodJob with other backends [\#51](https://github.com/bensheldon/good_job/issues/51)
11
141
 
12
142
  **Merged pull requests:**
data/README.md CHANGED
@@ -4,210 +4,327 @@ GoodJob is a multithreaded, Postgres-based, ActiveJob backend for Ruby on Rails.
4
4
 
5
5
  **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, ActiveJob, and Postgres to be simple and performant for most workloads.**
6
6
 
7
- - **Designed for ActiveJob.** Complete support for [async, queues, delays, priorities, timeouts, and retries](https://edgeguides.rubyonrails.org/active_job_basics.html) with near-zero configuration.
8
- - **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).
7
+ - **Designed for ActiveJob.** Complete support for [async, queues, delays, priorities, timeouts, and retries](https://edgeguides.rubyonrails.org/active_job_basics.html) with near-zero configuration.
8
+ - **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).
9
9
  - **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.
10
10
  - **For most workloads.** Targets full-stack teams, economy-minded solo developers, and applications that enqueue less than 1-million jobs/day.
11
11
 
12
12
  For more of the story of GoodJob, read the [introductory blog post](https://island94.org/2020/07/introducing-goodjob-1-0).
13
13
 
14
- <details>
14
+ <details markdown="1">
15
15
  <summary><strong>πŸ“Š Comparison of GoodJob with other job queue backends (click to expand)</strong></summary>
16
16
 
17
17
  | | Queues, priority, retries | Database | Concurrency | Reliability/Integrity | Latency |
18
18
  |-----------------|---------------------------|---------------------------------------|-------------------|------------------------|--------------------------|
19
19
  | **GoodJob** | βœ… Yes | βœ… Postgres | βœ… Multithreaded | βœ… ACID, Advisory Locks | βœ… Postgres LISTEN/NOTIFY |
20
- | **Que** | βœ… Yes | 🟨 Postgres, requires `structure.sql` | βœ… Multithreaded | βœ… ACID, Advisory Locks | βœ… Postgres LISTEN/NOTIFY |
21
- | **Delayed Job** | βœ… Yes | βœ… Postgres | πŸŸ₯ Single-threaded | βœ… ACID, record-based | 🟨 Polling |
22
- | **Sidekiq** | βœ… Yes | πŸŸ₯ Redis | βœ… Multithreaded | πŸŸ₯ Crashes lose jobs | βœ… Redis BRPOP |
23
- | **Sidekiq Pro** | βœ… Yes | πŸŸ₯ Redis | βœ… Multithreaded | βœ… Redis RPOPLPUSH | βœ… Redis RPOPLPUSH |
20
+ | **Que** | βœ… Yes | πŸ”ΆοΈ Postgres, requires `structure.sql` | βœ… Multithreaded | βœ… ACID, Advisory Locks | βœ… Postgres LISTEN/NOTIFY |
21
+ | **Delayed Job** | βœ… Yes | βœ… Postgres | πŸ”΄ Single-threaded | βœ… ACID, record-based | πŸ”Ά Polling |
22
+ | **Sidekiq** | βœ… Yes | πŸ”΄ Redis | βœ… Multithreaded | πŸ”΄ Crashes lose jobs | βœ… Redis BRPOP |
23
+ | **Sidekiq Pro** | βœ… Yes | πŸ”΄ Redis | βœ… Multithreaded | βœ… Redis RPOPLPUSH | βœ… Redis RPOPLPUSH |
24
24
 
25
25
  </details>
26
26
 
27
- ## Installation
27
+ ## Table of contents
28
+
29
+ - [Set up](#set-up)
30
+ - [Configuration](#configuration)
31
+ - [Command-line options](#command-line-options)
32
+ - [`good_job start`](#good_job-start)
33
+ - [`good_job cleanup_preserved_jobs`](#good_job-cleanup_preserved_jobs)
34
+ - [Adapter options](#adapter-options)
35
+ - [Global options](#global-options)
36
+ - [Dashboard](#dashboard)
37
+ - [Go deeper](#go-deeper)
38
+ - [Exceptions, retries, and reliability](#exceptions-retries-and-reliability)
39
+ - [Exceptions](#exceptions)
40
+ - [Retries](#retries)
41
+ - [ActionMailer retries](#actionmailer-retries)
42
+ - [Timeouts](#timeouts)
43
+ - [Optimize queues, threads, and processes](#optimize-queues-threads-and-processes)
44
+ - [Database connections](#database-connections)
45
+ - [Execute jobs async / in-process](#execute-jobs-async--in-process)
46
+ - [Migrate to GoodJob from a different ActiveJob backend](#migrate-to-goodjob-from-a-different-activejob-backend)
47
+ - [Monitor and preserve worked jobs](#monitor-and-preserve-worked-jobs)
48
+ - [Contribute](#contribute)
49
+ - [Gem development](#gem-development)
50
+ - [Release](#release)
51
+ - [License](#license)
52
+
53
+ ## Set up
54
+
55
+ 1. Add `good_job` to your application's Gemfile:
28
56
 
29
- Add this line to your application's Gemfile:
57
+ ```ruby
58
+ gem 'good_job'
59
+ ```
30
60
 
31
- ```ruby
32
- gem 'good_job'
33
- ```
61
+ 1. Install the gem:
34
62
 
35
- And then execute:
36
- ```bash
37
- $ bundle install
38
- ```
63
+ ```bash
64
+ $ bundle install
65
+ ```
39
66
 
40
- ## Usage
67
+ 1. Run the GoodJob install generator. This will generate a database migration to create a table for GoodJob's job records:
41
68
 
42
- 1. Create a database migration:
43
-
44
- ```bash
69
+ ```bash
45
70
  $ bin/rails g good_job:install
46
71
  ```
47
72
 
48
73
  Run the migration:
49
-
74
+
50
75
  ```bash
51
76
  $ bin/rails db:migrate
52
77
  ```
53
-
78
+
54
79
  1. Configure the ActiveJob adapter:
55
-
56
- ```ruby
80
+
81
+ ```ruby
57
82
  # config/application.rb
58
83
  config.active_job.queue_adapter = :good_job
59
84
  ```
60
-
61
- By default, using `:good_job` is equivalent to manually configuring the adapter:
62
-
85
+
86
+ 1. Inside of your application, queue your job πŸŽ‰:
87
+
63
88
  ```ruby
64
- # config/environments/development.rb
65
- config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :inline)
66
-
67
- # config/environments/test.rb
68
- config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :inline)
69
-
70
- # config/environments/production.rb
71
- config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :external)
89
+ YourJob.perform_later
72
90
  ```
73
91
 
74
- 1. Queue your job πŸŽ‰:
75
-
92
+ GoodJob supports all ActiveJob features:
93
+
76
94
  ```ruby
77
95
  YourJob.set(queue: :some_queue, wait: 5.minutes, priority: 10).perform_later
78
96
  ```
79
97
 
80
- 1. In production, the scheduler is designed to run in its own process:
81
-
82
- ```bash
83
- $ bundle exec good_job
84
- ```
85
-
86
- Configuration options available with `help`:
98
+ 1. In development, GoodJob executes jobs immediately. In production, GoodJob provides different options:
87
99
 
88
- ```bash
89
- $ bundle exec good_job help start
90
-
91
- Usage:
92
- good_job start
93
-
94
- Options:
95
- [--max-threads=N] # Maximum number of threads to use for working jobs (default: ActiveRecord::Base.connection_pool.size)
96
- [--queues=queue1,queue2(;queue3,queue4:5;-queue1,queue2)] # Queues to work from. Separate multiple queues with commas; exclude queues with a leading minus; separate isolated execution pools with semicolons and threads with colons (default: *)
97
- [--poll-interval=N] # Interval between polls for available jobs in seconds (default: 1)
98
-
99
- Start job worker
100
- ```
100
+ - 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:
101
101
 
102
- 1. Optimize execution to reduce congestion and execution latency.
102
+ ```bash
103
+ $ bundle exec good_job start
104
+ ```
103
105
 
104
- By default, GoodJob creates a single thread execution pool that will execute jobs from any queue. Depending on your application's workload, job types, and service level objectives, you may wish to optimize execution resources; for example, providing dedicated execution resources for transactional emails so they are not delayed by long-running batch jobs. Some options:
106
+ Ideally the command-line tool should be run on a separate machine or container from the web process. For example, on Heroku:
105
107
 
106
- - Multiple execution pools within a single process:
107
-
108
- ```bash
109
- $ bundle exec good_job --queues=transactional_messages:2;batch_processing:1;-transactional_messages,batch_processing:2;* --max-threads=5
108
+ ```Procfile
109
+ web: rails server
110
+ worker: bundle exec good_job start
110
111
  ```
111
-
112
- This configuration will result in a single process with 4 isolated thread execution pools. Isolated execution pools are separated with a semicolon (`;`) and queue names and thread counts with a colon (`:`)
113
-
114
- - `transactional_messages:2`: execute jobs enqueued on `transactional_messages` with up to 2 threads.
115
- - `batch_processing:1` execute jobs enqueued on `batch_processing` with a single thread.
116
- - `-transactional_messages,batch_processing`: execute jobs enqueued on _any_ queue _excluding_ `transactional_messages` or `batch_processing` with up to 2 threads.
117
- - `*`: execute jobs on any queue on up to 5 threads, as configured by `--max-threads=5`
118
-
119
- For moderate workloads, multiple isolated thread execution pools offers a good balance between congestion management and economy.
120
-
121
- Configuration can be injected by environment variables too:
122
-
123
- ```bash
124
- $ GOOD_JOB_QUEUES="transactional_messages:2;batch_processing:1;-transactional_messages,batch_processing:2;*" GOOD_JOB_MAX_THREADS=5 bundle exec good_job
112
+
113
+ The command-line tool supports a variety of options, see the reference below for command-line configuration.
114
+
115
+ - GoodJob can also be configured to execute jobs within the web server process to save on resources. This is useful for low-workloads when economy is paramount.
116
+
125
117
  ```
126
-
127
- - Multiple processes; for example, on Heroku:
128
-
129
- ```procfile
130
- # Procfile
131
-
132
- # Separate dyno types
133
- worker: bundle exec good_job --max-threads=5
134
- transactional_worker: bundle exec good_job --queues=transactional_messages --max-threads=2
135
- batch_worker: bundle exec good_job --queues=batch_processing --max-threads=1
136
-
137
- # Combined multi-process dyno
138
- combined_worker: bundle exec good_job --max-threads=5 & bundle exec good_job --queues=transactional_messages --max-threads=2 & bundle exec good_job --queues=batch_processing --max-threads=1 & wait -n
118
+ $ GOOD_JOB_EXECUTION_MODE=async rails server
139
119
  ```
140
-
141
- Running multiple processes can optimize for CPU performance at the expense of greater memory and system resource usage.
142
120
 
143
- _Keep in mind, queue operations and management is an advanced discipline. This stuff is complex, especially for heavy workloads and unique processing requirements. Good job πŸ‘_
121
+ Additional configuration is likely necessary, see the reference below for async configuration.
122
+
123
+ ## Configuration
124
+
125
+ ### Command-line options
126
+
127
+ There several top-level commands available through the `good_job` command-line tool.
128
+
129
+ Configuration options are available with `help`.
130
+
131
+ #### `good_job start`
132
+
133
+ `good_job start` executes queued jobs.
134
+
135
+ ```bash
136
+ $ bundle exec good_job help start
137
+
138
+ Usage:
139
+ good_job start
140
+
141
+ Options:
142
+ [--max-threads=COUNT] # Maximum number of threads to use for working jobs. (env var: GOOD_JOB_MAX_THREADS, default: 5)
143
+ [--queues=QUEUE_LIST] # Queues to work from. (env var: GOOD_JOB_QUEUES, default: *)
144
+ [--poll-interval=SECONDS] # Interval between polls for available jobs in seconds (env var: GOOD_JOB_POLL_INTERVAL, default: 1)
145
+
146
+ Executes queued jobs.
147
+
148
+ All options can be configured with environment variables.
149
+ See option descriptions for the matching environment variable name.
150
+
151
+ == Configuring queues
152
+ Separate multiple queues with commas; exclude queues with a leading minus;
153
+ separate isolated execution pools with semicolons and threads with colons.
154
+ ```
155
+
156
+ #### `good_job cleanup_preserved_jobs`
157
+
158
+ `good_job cleanup_preserved_jobs` deletes preserved job records. See [`GoodJob.preserve_job_records` for when this command is useful.
159
+
160
+ ```bash
161
+ $ bundle exec good_job help cleanup_preserved_jobs
162
+
163
+ Usage:
164
+ good_job cleanup_preserved_jobs
165
+
166
+ Options:
167
+ [--before-seconds-ago=SECONDS] # Delete records finished more than this many seconds ago (env var: GOOD_JOB_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO, default: 86400)
168
+
169
+ Deletes preserved job records.
170
+
171
+ By default, GoodJob deletes job records when the job is performed and this
172
+ command is not necessary.
173
+
174
+ However, when `GoodJob.preserve_job_records = true`, the jobs will be
175
+ preserved in the database. This is useful when wanting to analyze or
176
+ inspect job performance.
177
+
178
+ If you are preserving job records this way, use this command regularly
179
+ to delete old records and preserve space in your database.
180
+ ```
181
+
182
+ ### Adapter options
183
+
184
+ To use GoodJob, you can set `config.active_job.queue_adapter` to a `:good_job` or to an instance of `GoodJob::Adapter`, which you can configure with several options:
185
+
186
+ - `execution_mode` (symbol) specifies how and where jobs should be executed. You can also set this with the environment variable `GOOD_JOB_EXECUTION_MODE`. It can be any one of:
187
+ - `:inline` executes jobs immediately in whatever process queued them (usually the web server process). This should only be used in test and development environments.
188
+ - `:external` causes the adapter to enqueue jobs, but not execute them. When using this option (the default for production environments), you’ll need to use the command-line tool to actually execute your jobs.
189
+ - `:async` causes the adapter to execute you jobs in separate threads in whatever process queued them (usually the web process). This is akin to running the command-line tool’s code inside your web server. It can be more economical for small workloads (you don’t need a separate machine or environment for running your jobs), but if your web server is under heavy load or your jobs require a lot of resources, you should choose `:external` instead.
190
+ - `max_threads` (integer) sets the maximum number of threads to use when `execution_mode` is set to `:async`. You can also set this with the environment variable `GOOD_JOB_MAX_THREADS`.
191
+ - `queues` (string) determines which queues to execute jobs from when `execution_mode` is set to `:async`. See the description of `good_job start` for more details on the format of this string. You can also set this with the environment variable `GOOD_JOB_QUEUES`.
192
+ - `poll_interval` (integer) sets the number of seconds between polls for jobs when `execution_mode` is set to `:async`. You can also set this with the environment variable `GOOD_JOB_POLL_INTERVAL`.
193
+
194
+ Using the symbol instead of explicitly configuring the options above (i.e. setting `config.active_job.queue_adapter = :good_job`) is equivalent to:
195
+
196
+ ```ruby
197
+ # config/environments/development.rb
198
+ config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :inline)
199
+
200
+ # config/environments/test.rb
201
+ config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :inline)
202
+
203
+ # config/environments/production.rb
204
+ config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :external)
205
+ ```
206
+
207
+ ### Global options
208
+
209
+ Good Job’s general behavior can also be configured via several attributes directly on the `GoodJob` module:
210
+
211
+ - **`GoodJob.logger`** ([Rails Logger](https://api.rubyonrails.org/classes/ActiveSupport/Logger.html)) lets you set a custom logger for GoodJob. It should be an instance of a Rails `Logger`.
212
+ - **`GoodJob.preserve_job_records`** (boolean) keeps job records in your database even after jobs are completed. (Default: `false`)
213
+ - **`GoodJob.reperform_jobs_on_standard_error`** (boolean) causes jobs to be re-queued and retried if they raise an instance of `StandardError`. Instances of `Exception`, like SIGINT, will *always* be retried, regardless of this attribute’s value. (Default: `true`)
214
+ - **`GoodJob.on_thread_error`** (proc, lambda, or callable) will be called when an Exception. It can be useful for logging errors to bug tracking services, like Sentry or Airbrake.
215
+
216
+ You’ll generally want to configure these in `config/initializers/good_job.rb`, like so:
217
+
218
+ ```ruby
219
+ # config/initializers/good_job.rb
220
+ GoodJob.preserve_job_records = true
221
+ GoodJob.reperform_jobs_on_standard_error = false
222
+ GoodJob.on_thread_error = -> (exception) { Raven.capture_exception(exception) }
223
+ ```
224
+
225
+ ### Dashboard
226
+
227
+ _🚧 GoodJob's dashboard is a work in progress. Please contribute ideas and code on [Github](https://github.com/bensheldon/good_job/issues)._
144
228
 
145
- ### Error handling, retries, and reliability
229
+ GoodJob includes a Dashboard as a mountable `Rails::Engine`.
146
230
 
147
- GoodJob guarantees that a completely-performed job will run once and only once. GoodJob fully supports ActiveJob's built-in functionality for error handling, retries and timeouts. Writing reliable, transactional, and idempotent `ActiveJob#perform` methods is outside the scope of GoodJob.
231
+ 1. Explicitly require the Engine code at the top of your `config/application.rb` file, immediately after Rails is required. This is necessary because the mountable engine is an optional feature of GoodJob.
148
232
 
149
- #### Error handling
233
+ ```ruby
234
+ # config/application.rb
235
+ require_relative 'boot'
236
+
237
+ require 'rails/all'
238
+ require 'good_job/engine' # <= Add this line
239
+ # ...
240
+ ```
241
+
242
+ 1. Mount the engine in your `config/routes.rb` file. The following will mount it at `http://example.com/good_job`.
243
+
244
+ ```ruby
245
+ # config/routes.rb
246
+ # ...
247
+ mount GoodJob::Engine => 'good_job'
248
+ ```
150
249
 
151
- By default, if a job raises an error while it is being performed, _and it bubbles up to the GoodJob backend_, GoodJob will be immediately re-perform the job until it finishes successfully.
250
+ Because jobs can potentially contain sensitive information, you should authorize access. For example, using Devise's `authenticate` helper, that might look like:
251
+
252
+ ```ruby
253
+ # config/routes.rb
254
+ # ...
255
+ authenticate :user, ->(user) { user.admin? } do
256
+ mount GoodJob::Engine => 'good_job'
257
+ end
258
+ ```
259
+
260
+ Another option is using basic auth like this:
152
261
 
153
- - `Exception`-type errors, such as a SIGINT, will always cause a job to be re-performed.
154
- - `StandardError`-type errors, by default, will cause a job to be re-performed, though this is configurable:
155
-
156
262
  ```ruby
157
263
  # config/initializers/good_job.rb
158
- GoodJob.reperform_jobs_on_standard_error = true # => default
264
+ GoodJob::Engine.middleware.use(Rack::Auth::Basic) do |username, password|
265
+ ActiveSupport::SecurityUtils.secure_compare(Rails.application.credentials.good_job_username, username) &&
266
+ ActiveSupport::SecurityUtils.secure_compare(Rails.application.credentials.good_job_password, password)
267
+ end
159
268
  ```
160
269
 
161
- To report errors that _do_ bubble up to the GoodJob backend, assign a callable to `GoodJob.on_thread_error`. For example:
270
+ ## Go deeper
271
+
272
+ ### Exceptions, retries, and reliability
273
+
274
+ GoodJob guarantees that a completely-performed job will run once and only once. GoodJob fully supports ActiveJob's built-in functionality for error handling, retries and timeouts.
275
+
276
+ #### Exceptions
277
+
278
+ ActiveJob 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.
279
+
280
+ 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.):
162
281
 
163
282
  ```ruby
164
283
  # config/initializers/good_job.rb
165
-
166
- # With Sentry (or Bugsnag, Airbrake, Honeybadger, etc.)
167
284
  GoodJob.on_thread_error = -> (exception) { Raven.capture_exception(exception) }
168
285
  ```
169
286
 
170
- ### Retrying jobs
287
+ #### Retries
171
288
 
172
- ActiveJob can be configured to retry an infinite number of times, with an exponential backoff. Using ActiveJob's `retry_on` will ensure that errors do not bubble up to the GoodJob backend:
289
+ By default, GoodJob will automatically and immediately retry a job when an exception is raised to GoodJob.
290
+
291
+ However, ActiveJob can be configured to retry an infinite number of times, with an exponential backoff. Using ActiveJob's `retry_on` prevents exceptions from reaching GoodJob:
173
292
 
174
293
  ```ruby
175
- class ApplicationJob < ActiveJob::Base
294
+ class ApplicationJob < ActiveJob::Base
176
295
  retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
177
296
  # ...
178
297
  end
179
298
  ```
180
299
 
181
- When specifying a limited number of retries, care must be taken to ensure that an error does not bubble up to the GoodJob backend because that will result in the job being re-performed:
300
+ When using `retry_on` with _a limited number of retries_, the final exception will not be rescued and will raise to GoodJob. GoodJob can be configured to discard un-handled exceptions instead of retrying them:
182
301
 
183
302
  ```ruby
184
- class ApplicationJob < ActiveJob::Base
303
+ # config/initializers/good_job.rb
304
+ GoodJob.reperform_jobs_on_standard_error = false
305
+ ```
306
+
307
+ Alternatively, pass a block to `retry_on` to handle the final exception instead of raising it to GoodJob:
308
+
309
+ ```ruby
310
+ class ApplicationJob < ActiveJob::Base
185
311
  retry_on StandardError, attempts: 5 do |_job, _exception|
186
- # Log error, etc.
187
- # You must implement this block, otherwise,
188
- # Active Job will re-raise the error.
189
- # Do not re-raise the error, otherwise
190
- # GoodJob will immediately re-perform the job.
312
+ # Log error, do nothing, etc.
191
313
  end
192
314
  # ...
193
315
  end
194
316
  ```
195
317
 
196
- GoodJob can be configured to allow omitting `retry_on`'s block argument and implicitly discard un-handled errors:
318
+ When using `retry_on` with an infinite number of retries, exceptions will never be raised to GoodJob, which means `GoodJob.on_thread_error` will never be called. To report log or report exceptions to an exception monitoring service (e.g. Sentry, Bugsnag, Airbrake, Honeybadger, etc), create an explicit exception wrapper. For example:
197
319
 
198
320
  ```ruby
199
- # config/initializers/good_job.rb
200
-
201
- # Do NOT re-perform a job if a StandardError bubbles up to the GoodJob backend
202
- GoodJob.reperform_jobs_on_standard_error = false
203
- ```
321
+ class ApplicationJob < ActiveJob::Base
322
+ retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
204
323
 
205
- When using an exception monitoring service (e.g. Sentry, Bugsnag, Airbrake, Honeybadger, etc), the use of `rescue_on` may be incompatible with their ActiveJob integration. It's safest to explicitly wrap jobs with an exception reporter. For example:
324
+ retry_on SpecialError, attempts: 5 do |_job, exception|
325
+ Raven.capture_exception(exception)
326
+ end
206
327
 
207
- ```ruby
208
- class ApplicationJob < ActiveJob::Base
209
- retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
210
-
211
328
  around_perform do |_job, block|
212
329
  block.call
213
330
  rescue StandardError => e
@@ -218,19 +335,18 @@ class ApplicationJob < ActiveJob::Base
218
335
  end
219
336
  ```
220
337
 
221
-
222
- ActiveJob's `discard_on` functionality is supported too.
223
-
224
338
  #### ActionMailer retries
225
339
 
226
- Using a Mailer's `#deliver_later` will enqueue an instance of `ActionMailer::DeliveryJob` which inherits from `ActiveJob::Base` rather than your applications `ApplicationJob`. You can use an initializer to configure retries on `ActionMailer::DeliveryJob`:
340
+ Any configuration in `ApplicationJob` will have to be duplicated on `ActionMailer::MailDeliveryJob` (`ActionMailer::DeliveryJob` in Rails 5.2 or earlier) because ActionMailer uses a custom class, `ActionMailer::MailDeliveryJob`, which inherits from `ActiveJob::Base`, rather than your applications `ApplicationJob`.
341
+
342
+ You can use an initializer to configure `ActionMailer::MailDeliveryJob`, for example:
227
343
 
228
344
  ```ruby
229
345
  # config/initializers/good_job.rb
230
- ActionMailer::DeliveryJob.retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
346
+ ActionMailer::MailDeliveryJob.retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
231
347
 
232
348
  # With Sentry (or Bugsnag, Airbrake, Honeybadger, etc.)
233
- ActionMailer::DeliveryJob.around_perform do |_job, block|
349
+ ActionMailer::MailDeliveryJob.around_perform do |_job, block|
234
350
  block.call
235
351
  rescue StandardError => e
236
352
  Raven.capture_exception(e)
@@ -238,14 +354,17 @@ rescue StandardError => e
238
354
  end
239
355
  ```
240
356
 
241
- #### Timeouts
357
+ Note, that `ActionMailer::MailDeliveryJob` is a default since Rails 6.0. Be sure that your app is using that class, as it
358
+ might also be configured to use (deprecated now) `ActionMailer::DeliveryJob`.
359
+
360
+ ### Timeouts
242
361
 
243
362
  Job timeouts can be configured with an `around_perform`:
244
363
 
245
364
  ```ruby
246
- class ApplicationJob < ActiveJob::Base
365
+ class ApplicationJob < ActiveJob::Base
247
366
  JobTimeoutError = Class.new(StandardError)
248
-
367
+
249
368
  around_perform do |_job, block|
250
369
  # Timeout jobs after 10 minutes
251
370
  Timeout.timeout(10.minutes, JobTimeoutError) do
@@ -255,20 +374,61 @@ class ApplicationJob < ActiveJob::Base
255
374
  end
256
375
  ```
257
376
 
258
- ### Configuring job execution threads
259
-
260
- GoodJob executes enqueued jobs using threads. There is a lot than can be said about [multithreaded behavior in Ruby on Rails](https://guides.rubyonrails.org/threading_and_code_execution.html), but briefly:
377
+ ### Optimize queues, threads, and processes
378
+
379
+ By default, GoodJob creates a single thread execution pool that will execute jobs from any queue. Depending on your application's workload, job types, and service level objectives, you may wish to optimize execution resources. For example, providing dedicated execution resources for transactional emails so they are not delayed by long-running batch jobs. Some options:
380
+
381
+ - Multiple execution pools within a single process:
382
+
383
+ ```bash
384
+ $ bundle exec good_job --queues="transactional_messages:2;batch_processing:1;-transactional_messages,batch_processing:2;*" --max-threads=5
385
+ ```
386
+
387
+ This configuration will result in a single process with 4 isolated thread execution pools. Isolated execution pools are separated with a semicolon (`;`) and queue names and thread counts with a colon (`:`)
261
388
 
262
- - Each GoodJob execution thread requires its own database connection, which are automatically checked out from Rails’s connection pool. _Allowing GoodJob to schedule more threads than are available in the database connection pool can lead to timeouts and is not recommended._
263
- - The maximum number of GoodJob threads can be configured, in decreasing precedence:
264
- 1. `$ bundle exec good_job --max_threads 4`
265
- 2. `$ GOOD_JOB_MAX_THREADS=4 bundle exec good_job`
266
- 3. `$ RAILS_MAX_THREADS=4 bundle exec good_job`
267
- 4. Implicitly via Rails's database connection pool size (`ActiveRecord::Base.connection_pool.size`)
389
+ - `transactional_messages:2`: execute jobs enqueued on `transactional_messages` with up to 2 threads.
390
+ - `batch_processing:1` execute jobs enqueued on `batch_processing` with a single thread.
391
+ - `-transactional_messages,batch_processing`: execute jobs enqueued on _any_ queue _excluding_ `transactional_messages` or `batch_processing` with up to 2 threads.
392
+ - `*`: execute jobs on any queue on up to 5 threads, as configured by `--max-threads=5`
268
393
 
269
- ### Executing jobs async / in-process
394
+ For moderate workloads, multiple isolated thread execution pools offers a good balance between congestion management and economy.
270
395
 
271
- GoodJob is able to run "async" in the same process as the webserver (e.g. `bin/rail s`). GoodJob's async execution mode offers benefits of economy by not requiring a separate job worker process, but with the tradeoff of increased complexity. Async mode can be configured in two ways:
396
+ Configuration can be injected by environment variables too:
397
+
398
+ ```bash
399
+ $ GOOD_JOB_QUEUES="transactional_messages:2;batch_processing:1;-transactional_messages,batch_processing:2;*" GOOD_JOB_MAX_THREADS=5 bundle exec good_job
400
+ ```
401
+
402
+ - Multiple processes; for example, on Heroku:
403
+
404
+ ```procfile
405
+ # Procfile
406
+
407
+ # Separate dyno types
408
+ worker: bundle exec good_job --max-threads=5
409
+ transactional_worker: bundle exec good_job --queues="transactional_messages" --max-threads=2
410
+ batch_worker: bundle exec good_job --queues="batch_processing" --max-threads=1
411
+
412
+ # Combined multi-process dyno
413
+ combined_worker: bundle exec good_job --max-threads=5 & bundle exec good_job --queues="transactional_messages" --max-threads=2 & bundle exec good_job --queues="batch_processing" --max-threads=1 & wait -n
414
+ ```
415
+
416
+ Running multiple processes can optimize for CPU performance at the expense of greater memory and system resource usage.
417
+
418
+ Keep in mind, queue operations and management is an advanced discipline. This stuff is complex, especially for heavy workloads and unique processing requirements. Good job πŸ‘
419
+
420
+ ### Database connections
421
+
422
+ Each GoodJob execution thread requires its own database connection that is automatically checked out from Rails’s connection pool. _Allowing GoodJob to create more threads than available database connections can lead to timeouts and is not recommended._ For example:
423
+
424
+ ```yaml
425
+ # config/database.yml
426
+ pool: <%= [ENV.fetch("RAILS_MAX_THREADS", 5).to_i, ENV.fetch("GOOD_JOB_MAX_THREADS", 4).to_i].max %>
427
+ ```
428
+
429
+ ### Execute jobs async / in-process
430
+
431
+ GoodJob can execute jobs "async" in the same process as the webserver (e.g. `bin/rail s`). GoodJob's async execution mode offers benefits of economy by not requiring a separate job worker process, but with the tradeoff of increased complexity. Async mode can be configured in two ways:
272
432
 
273
433
  - Directly configure the ActiveJob adapter:
274
434
 
@@ -276,12 +436,13 @@ GoodJob is able to run "async" in the same process as the webserver (e.g. `bin/r
276
436
  # config/environments/production.rb
277
437
  config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :async, max_threads: 4, poll_interval: 30)
278
438
  ```
439
+
279
440
  - Or, when using `...queue_adapter = :good_job`, via environment variables:
280
441
 
281
442
  ```bash
282
443
  $ GOOD_JOB_EXECUTION_MODE=async GOOD_JOB_MAX_THREADS=4 GOOD_JOB_POLL_INTERVAL=30 bin/rails server
283
444
  ```
284
-
445
+
285
446
  Depending on your application configuration, you may need to take additional steps:
286
447
 
287
448
  - Ensure that you have enough database connections for both web and job execution threads:
@@ -295,28 +456,28 @@ Depending on your application configuration, you may need to take additional ste
295
456
 
296
457
  ```ruby
297
458
  # config/puma.rb
298
-
459
+
299
460
  before_fork do
300
461
  GoodJob.shutdown
301
462
  end
302
-
463
+
303
464
  on_worker_boot do
304
465
  GoodJob.restart
305
466
  end
306
-
467
+
307
468
  on_worker_shutdown do
308
469
  GoodJob.shutdown
309
470
  end
310
-
471
+
311
472
  MAIN_PID = Process.pid
312
473
  at_exit do
313
474
  GoodJob.shutdown if Process.pid == MAIN_PID
314
475
  end
315
476
  ```
316
-
477
+
317
478
  GoodJob is compatible with Puma's `preload_app!` method.
318
-
319
- ### Migrating to GoodJob from a different ActiveJob backend
479
+
480
+ ### Migrate to GoodJob from a different ActiveJob backend
320
481
 
321
482
  If your application is already using an ActiveJob backend, you will need to install GoodJob to enqueue and perform newly created jobs _and_ finish performing pre-existing jobs on the previous backend.
322
483
 
@@ -331,7 +492,7 @@ If your application is already using an ActiveJob backend, you will need to inst
331
492
  ```
332
493
 
333
494
  1. Continue running executors for both backends. For example, on Heroku it's possible to run [two processes](https://help.heroku.com/CTFS2TJK/how-do-i-run-multiple-processes-on-a-dyno) within the same dyno:
334
-
495
+
335
496
  ```procfile
336
497
  # Procfile
337
498
  # ...
@@ -340,11 +501,11 @@ If your application is already using an ActiveJob backend, you will need to inst
340
501
 
341
502
  1. Once you are confident that no unperformed jobs remain in the previous ActiveJob backend, code and configuration for that backend can be completely removed.
342
503
 
343
- ### Monitoring and preserving worked jobs
504
+ ### Monitor and preserve worked jobs
344
505
 
345
506
  GoodJob is fully instrumented with [`ActiveSupport::Notifications`](https://edgeguides.rubyonrails.org/active_support_instrumentation.html#introduction-to-instrumentation).
346
507
 
347
- By default, GoodJob will delete job records after they are run, regardless of whether they succeed or not (raising a kind of `StandardError`), unless they are interrupted (raising a kind of `Exception`).
508
+ By default, GoodJob will delete job records after they are run, regardless of whether they succeed or not (raising a kind of `StandardError`), unless they are interrupted (raising a kind of `Exception`).
348
509
 
349
510
  To preserve job records for later inspection, set an initializer:
350
511
 
@@ -356,7 +517,7 @@ GoodJob.preserve_job_records = true
356
517
  It is also necessary to delete these preserved jobs from the database after a certain time period:
357
518
 
358
519
  - For example, in a Rake task:
359
-
520
+
360
521
  ```ruby
361
522
  GoodJob::Job.finished(1.day.ago).delete_all
362
523
  ```
@@ -367,7 +528,7 @@ It is also necessary to delete these preserved jobs from the database after a ce
367
528
  $ bundle exec good_job cleanup_preserved_jobs --before-seconds-ago=86400
368
529
  ```
369
530
 
370
- ## Contributing
531
+ ## Contribute
371
532
 
372
533
  Contributions are welcomed and appreciated πŸ™
373
534
 
@@ -412,7 +573,7 @@ $ bundle install
412
573
  # => Using good_job 0.1.0 from https://github.com/bensheldon/good_job.git (at /Users/You/Projects/good_job@dc57fb0)
413
574
  ```
414
575
 
415
- ### Releasing
576
+ ### Release
416
577
 
417
578
  Package maintainers can release this gem by running:
418
579
 
@@ -426,7 +587,7 @@ $ gem signin
426
587
  # Update version number, changelog, and create git commit:
427
588
  $ bundle exec rake release[minor] # major,minor,patch
428
589
 
429
- # ..and follow subsequent directions.
590
+ # ..and follow subsequent directions.
430
591
  ```
431
592
 
432
593
  ## License