good_job 1.2.3 → 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ea00429e2b1515df6973f66c81d1827acdb4528e39ac811ece90a69fbd0b4f6
4
- data.tar.gz: 9d3c7e104fda0d102789fc97fb716e5372c6e746d169fb521b84ecf13312ce24
3
+ metadata.gz: 1f3fa6d323c18dfb49aaf3b87f0ca71492a935752e7ca140880b68daa72a60f9
4
+ data.tar.gz: 999b400b7e1dd22206898fb1cdc35f6255088ce94c3562fa48fe97fc20a23672
5
5
  SHA512:
6
- metadata.gz: 7f34e2681a4642c9c337dd76253950a46d1edbff21feb6940eace1fa99b63d3d919f1eb3b2ae56b90d06d0697229c47ac581998be8615abc594c308255325fb1
7
- data.tar.gz: fc69543344585cbfc7cb7608cce5884526481cbf75474a70d2ddea5737ff1eaea722743ad1508e683a2bbeda91e4399d25c8b1294cb3a763d1436b36ece74b77
6
+ metadata.gz: 1b9236562e20d4da1e5738d9b143fabe9377d854b392b6b0eb2d77c0009d9f8a0c82ef94b414446a7b5db0b2a43e477ad4b8a6c7bff737b69c9d8a744ee29151
7
+ data.tar.gz: cfcc994ea2f6e9a26c3b1115ccb2df6383e2897c3db891415745b86769dbdc411a62b7d60c89aa7ddb6880009c6124c795cef33efff55daa860ed7fd90e1b81d
@@ -1,5 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.2.4](https://github.com/bensheldon/good_job/tree/v1.2.4) (2020-09-01)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.3...v1.2.4)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Add environment variable to mirror `cleanup\_preserved\_jobs --before-seconds-ago=SECONDS` [\#110](https://github.com/bensheldon/good_job/issues/110)
10
+
11
+ **Closed issues:**
12
+
13
+ - Remove unused PgLocks class [\#121](https://github.com/bensheldon/good_job/issues/121)
14
+ - Fix minor issue with CommandLine option links in README.md [\#116](https://github.com/bensheldon/good_job/issues/116)
15
+ - Unused .advisory\_lock\_details in PgLocks [\#105](https://github.com/bensheldon/good_job/issues/105)
16
+
17
+ **Merged pull requests:**
18
+
19
+ - Remove unused PgLocks class [\#120](https://github.com/bensheldon/good_job/pull/120) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
20
+ - Better table name detection for Job queries [\#119](https://github.com/bensheldon/good_job/pull/119) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
21
+ - Fix readme CommandLine option links [\#115](https://github.com/bensheldon/good_job/pull/115) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
22
+ - Allow env variable config for cleanups [\#114](https://github.com/bensheldon/good_job/pull/114) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
23
+ - Have YARD render markdown files with GFM \(Github Flavored Markdown\) [\#113](https://github.com/bensheldon/good_job/pull/113) ([bensheldon](https://github.com/bensheldon))
24
+ - Add markdownlint to lint readme [\#109](https://github.com/bensheldon/good_job/pull/109) ([bensheldon](https://github.com/bensheldon))
25
+ - Remove unused method in PgLocks [\#107](https://github.com/bensheldon/good_job/pull/107) ([gadimbaylisahil](https://github.com/gadimbaylisahil))
26
+ - Re-organize Readme: frontload configuration, add Table of Contents [\#106](https://github.com/bensheldon/good_job/pull/106) ([bensheldon](https://github.com/bensheldon))
27
+
3
28
  ## [v1.2.3](https://github.com/bensheldon/good_job/tree/v1.2.3) (2020-08-27)
4
29
 
5
30
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.2.2...v1.2.3)
@@ -63,6 +88,7 @@
63
88
  **Merged pull requests:**
64
89
 
65
90
  - Document GoodJob module [\#83](https://github.com/bensheldon/good_job/pull/83) ([bensheldon](https://github.com/bensheldon))
91
+ - Add Postgres LISTEN/NOTIFY support [\#82](https://github.com/bensheldon/good_job/pull/82) ([bensheldon](https://github.com/bensheldon))
66
92
 
67
93
  ## [v1.1.4](https://github.com/bensheldon/good_job/tree/v1.1.4) (2020-08-19)
68
94
 
@@ -75,7 +101,6 @@
75
101
 
76
102
  **Merged pull requests:**
77
103
 
78
- - Add Postgres LISTEN/NOTIFY support [\#82](https://github.com/bensheldon/good_job/pull/82) ([bensheldon](https://github.com/bensheldon))
79
104
  - Allow Schedulers to filter \#create\_thread to avoid flood of queries when running async with multiple schedulers [\#81](https://github.com/bensheldon/good_job/pull/81) ([bensheldon](https://github.com/bensheldon))
80
105
  - Fully name scheduler threadpools and thread names; refactor CLI STDOUT [\#80](https://github.com/bensheldon/good_job/pull/80) ([bensheldon](https://github.com/bensheldon))
81
106
 
@@ -157,10 +182,6 @@
157
182
 
158
183
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.0.1...v1.0.2)
159
184
 
160
- **Fixed bugs:**
161
-
162
- - Fix counting of available execution threads [\#58](https://github.com/bensheldon/good_job/pull/58) ([bensheldon](https://github.com/bensheldon))
163
-
164
185
  **Merged pull requests:**
165
186
 
166
187
  - Add migration generator [\#56](https://github.com/bensheldon/good_job/pull/56) ([thedanbob](https://github.com/thedanbob))
@@ -182,6 +203,10 @@
182
203
 
183
204
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v0.8.2...v0.9.0)
184
205
 
206
+ **Fixed bugs:**
207
+
208
+ - Fix counting of available execution threads [\#58](https://github.com/bensheldon/good_job/pull/58) ([bensheldon](https://github.com/bensheldon))
209
+
185
210
  **Merged pull requests:**
186
211
 
187
212
  - Allow preservation of finished job records [\#46](https://github.com/bensheldon/good_job/pull/46) ([bensheldon](https://github.com/bensheldon))
@@ -262,6 +287,7 @@
262
287
 
263
288
  - Improve ActiveRecord usage for advisory locking [\#24](https://github.com/bensheldon/good_job/pull/24) ([bensheldon](https://github.com/bensheldon))
264
289
  - Remove support for Rails 5.1 [\#23](https://github.com/bensheldon/good_job/pull/23) ([bensheldon](https://github.com/bensheldon))
290
+ - Clean up Gemspec [\#15](https://github.com/bensheldon/good_job/pull/15) ([bensheldon](https://github.com/bensheldon))
265
291
 
266
292
  ## [v0.3.0](https://github.com/bensheldon/good_job/tree/v0.3.0) (2020-03-22)
267
293
 
@@ -289,7 +315,6 @@
289
315
 
290
316
  **Merged pull requests:**
291
317
 
292
- - Clean up Gemspec [\#15](https://github.com/bensheldon/good_job/pull/15) ([bensheldon](https://github.com/bensheldon))
293
318
  - Set up Rubocop [\#14](https://github.com/bensheldon/good_job/pull/14) ([bensheldon](https://github.com/bensheldon))
294
319
  - Add pg gem as explicit dependency [\#13](https://github.com/bensheldon/good_job/pull/13) ([bensheldon](https://github.com/bensheldon))
295
320
  - Bump nokogiri from 1.10.7 to 1.10.9 [\#12](https://github.com/bensheldon/good_job/pull/12) ([dependabot[bot]](https://github.com/apps/dependabot))
data/README.md CHANGED
@@ -4,210 +4,281 @@ 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
+ - [Going deeper](#going-deeper)
37
+ - [Exceptions, retries, and reliability](#exceptions-retries-and-reliability)
38
+ - [Exceptions](#exceptions)
39
+ - [Retries](#retries)
40
+ - [ActionMailer retries](#actionmailer-retries)
41
+ - [Timeouts](#timeouts)
42
+ - [Optimize queues, threads, and processes](#optimize-queues-threads-and-processes)
43
+ - [Database connections](#database-connections)
44
+ - [Executing jobs async / in-process](#executing-jobs-async--in-process)
45
+ - [Migrating to GoodJob from a different ActiveJob backend](#migrating-to-goodjob-from-a-different-activejob-backend)
46
+ - [Monitoring and preserving worked jobs](#monitoring-and-preserving-worked-jobs)
47
+ - [Contributing](#contributing)
48
+ - [Gem development](#gem-development)
49
+ - [Releasing](#releasing)
50
+ - [License](#license)
51
+
52
+ ## Set up
53
+
54
+ 1. Add `good_job` to your application's Gemfile:
28
55
 
29
- Add this line to your application's Gemfile:
56
+ ```ruby
57
+ gem 'good_job'
58
+ ```
30
59
 
31
- ```ruby
32
- gem 'good_job'
33
- ```
60
+ 1. Install the gem:
34
61
 
35
- And then execute:
36
- ```bash
37
- $ bundle install
38
- ```
62
+ ```bash
63
+ $ bundle install
64
+ ```
39
65
 
40
- ## Usage
66
+ 1. Run the GoodJob install generator. This will generate a database migration to create a table for GoodJob's job records:
41
67
 
42
- 1. Create a database migration:
43
-
44
- ```bash
68
+ ```bash
45
69
  $ bin/rails g good_job:install
46
70
  ```
47
71
 
48
72
  Run the migration:
49
-
73
+
50
74
  ```bash
51
75
  $ bin/rails db:migrate
52
76
  ```
53
-
77
+
54
78
  1. Configure the ActiveJob adapter:
55
-
56
- ```ruby
79
+
80
+ ```ruby
57
81
  # config/application.rb
58
82
  config.active_job.queue_adapter = :good_job
59
83
  ```
60
-
61
- By default, using `:good_job` is equivalent to manually configuring the adapter:
62
-
84
+
85
+ 1. Inside of your application, queue your job 🎉:
86
+
63
87
  ```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)
88
+ YourJob.perform_later
72
89
  ```
73
90
 
74
- 1. Queue your job 🎉:
75
-
91
+ GoodJob supports all ActiveJob features:
92
+
76
93
  ```ruby
77
94
  YourJob.set(queue: :some_queue, wait: 5.minutes, priority: 10).perform_later
78
95
  ```
79
96
 
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`:
97
+ 1. In development, GoodJob executes jobs immediately. In production, GoodJob provides different options:
87
98
 
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
- ```
99
+ - 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
100
 
102
- 1. Optimize execution to reduce congestion and execution latency.
101
+ ```bash
102
+ $ bundle exec good_job start
103
+ ```
103
104
 
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:
105
+ Ideally the command-line tool should be run on a separate machine or container from the web process. For example, on Heroku:
105
106
 
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
107
+ ```Procfile
108
+ web: rails server
109
+ worker: bundle exec good_job start
110
110
  ```
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
111
+
112
+ The command-line tool supports a variety of options, see the reference below for command-line configuration.
113
+
114
+ - 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.
115
+
125
116
  ```
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
117
+ $ GOOD_JOB_EXECUTION_MODE=async rails server
139
118
  ```
140
-
141
- Running multiple processes can optimize for CPU performance at the expense of greater memory and system resource usage.
142
119
 
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 👍_
120
+ Additional configuration is likely necessary, see the reference below for async configuration.
144
121
 
145
- ### Error handling, retries, and reliability
122
+ ## Configuration
146
123
 
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.
124
+ ### Command-line options
148
125
 
149
- #### Error handling
126
+ There several top-level commands available through the `good_job` command-line tool.
150
127
 
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.
128
+ Configuration options are available with `help`.
152
129
 
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
- ```ruby
157
- # config/initializers/good_job.rb
158
- GoodJob.reperform_jobs_on_standard_error = true # => default
159
- ```
130
+ #### `good_job start`
131
+
132
+ `good_job start` executes queued jobs.
133
+
134
+ ```bash
135
+ $ bundle exec good_job help start
136
+
137
+ Usage:
138
+ good_job start
139
+
140
+ Options:
141
+ [--max-threads=COUNT] # Maximum number of threads to use for working jobs. (env var: GOOD_JOB_MAX_THREADS, default: 5)
142
+ [--queues=QUEUE_LIST] # Queues to work from. (env var: GOOD_JOB_QUEUES, default: *)
143
+ [--poll-interval=SECONDS] # Interval between polls for available jobs in seconds (env var: GOOD_JOB_POLL_INTERVAL, default: 1)
144
+
145
+ Executes queued jobs.
146
+
147
+ All options can be configured with environment variables.
148
+ See option descriptions for the matching environment variable name.
149
+
150
+ == Configuring queues
151
+ Separate multiple queues with commas; exclude queues with a leading minus;
152
+ separate isolated execution pools with semicolons and threads with colons.
153
+ ```
154
+
155
+ #### `good_job cleanup_preserved_jobs`
156
+
157
+ `good_job cleanup_preserved_jobs` deletes preserved job records. See [`GoodJob.preserve_job_records` for when this command is useful.
158
+
159
+ ```bash
160
+ $ bundle exec good_job help cleanup_preserved_jobs
161
+
162
+ Usage:
163
+ good_job cleanup_preserved_jobs
164
+
165
+ Options:
166
+ [--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)
167
+
168
+ Deletes preserved job records.
169
+
170
+ By default, GoodJob deletes job records when the job is performed and this
171
+ command is not necessary.
172
+
173
+ However, when `GoodJob.preserve_job_records = true`, the jobs will be
174
+ preserved in the database. This is useful when wanting to analyze or
175
+ inspect job performance.
176
+
177
+ If you are preserving job records this way, use this command regularly
178
+ to delete old records and preserve space in your database.
179
+ ```
180
+
181
+ ### Adapter options
182
+
183
+ 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:
184
+
185
+ - `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:
186
+ - `:inline` executes jobs immediately in whatever process queued them (usually the web server process). This should only be used in test and development environments.
187
+ - `:external` causes the adapter to equeue 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.
188
+ - `: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.
189
+ - `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`.
190
+ - `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`.
191
+ - `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`.
192
+
193
+ Using the symbol instead of explicitly configuring the options above (i.e. setting `config.active_job.queue_adapter = :good_job`) is equivalent to:
194
+
195
+ ```ruby
196
+ # config/environments/development.rb
197
+ config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :inline)
198
+
199
+ # config/environments/test.rb
200
+ config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :inline)
201
+
202
+ # config/environments/production.rb
203
+ config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :external)
204
+ ```
205
+
206
+ ### Global options
207
+
208
+ Good Job’s general behavior can also be configured via several attributes directly on the `GoodJob` module:
209
+
210
+ - **`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`.
211
+ - **`GoodJob.preserve_job_records`** (boolean) keeps job records in your database even after jobs are completed. (Default: `false`)
212
+ - **`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`)
213
+ - **`GoodJob.on_thread_error`** (proc, lambda, or callable) will be called when a job raises an error. It can be useful for logging errors to bug tracking services, like Sentry or Airbrake.
160
214
 
161
- To report errors that _do_ bubble up to the GoodJob backend, assign a callable to `GoodJob.on_thread_error`. For example:
215
+ You’ll generally want to configure these in `config/initializers/good_job.rb`, like so:
162
216
 
163
217
  ```ruby
164
218
  # config/initializers/good_job.rb
219
+ GoodJob.preserve_job_records = true
220
+ GoodJob.reperform_jobs_on_standard_error = false
221
+ GoodJob.on_thread_error = -> (exception) { Raven.capture_exception(exception) }
222
+ ```
165
223
 
166
- # With Sentry (or Bugsnag, Airbrake, Honeybadger, etc.)
224
+ ## Going deeper
225
+
226
+ ### Exceptions, retries, and reliability
227
+
228
+ 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.
229
+
230
+ #### Exceptions
231
+
232
+ 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.
233
+
234
+ 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.):
235
+
236
+ ```ruby
237
+ # config/initializers/good_job.rb
167
238
  GoodJob.on_thread_error = -> (exception) { Raven.capture_exception(exception) }
168
239
  ```
169
240
 
170
- ### Retrying jobs
241
+ #### Retries
171
242
 
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:
243
+ By default, GoodJob will automatically and immediately retry a job when an exception is raised to GoodJob.
244
+
245
+ 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
246
 
174
247
  ```ruby
175
- class ApplicationJob < ActiveJob::Base
248
+ class ApplicationJob < ActiveJob::Base
176
249
  retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
177
250
  # ...
178
251
  end
179
252
  ```
180
253
 
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:
254
+ 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
255
 
183
256
  ```ruby
184
- class ApplicationJob < ActiveJob::Base
257
+ # config/initializers/good_job.rb
258
+ GoodJob.reperform_jobs_on_standard_error = false
259
+ ```
260
+
261
+ Alternatively, pass a block to `retry_on` to handle the final exception instead of raising it to GoodJob:
262
+
263
+ ```ruby
264
+ class ApplicationJob < ActiveJob::Base
185
265
  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.
266
+ # Log error, do nothing, etc.
191
267
  end
192
268
  # ...
193
269
  end
194
270
  ```
195
271
 
196
- GoodJob can be configured to allow omitting `retry_on`'s block argument and implicitly discard un-handled errors:
272
+ 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
273
 
198
274
  ```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
- ```
275
+ class ApplicationJob < ActiveJob::Base
276
+ retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
204
277
 
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:
278
+ retry_on SpecialError, attempts: 5 do |_job, exception|
279
+ Raven.capture_exception(exception)
280
+ end
206
281
 
207
- ```ruby
208
- class ApplicationJob < ActiveJob::Base
209
- retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
210
-
211
282
  around_perform do |_job, block|
212
283
  block.call
213
284
  rescue StandardError => e
@@ -218,12 +289,11 @@ class ApplicationJob < ActiveJob::Base
218
289
  end
219
290
  ```
220
291
 
221
-
222
- ActiveJob's `discard_on` functionality is supported too.
223
-
224
292
  #### ActionMailer retries
225
293
 
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`:
294
+ Any configuration in `ApplicationJob` will have to be duplicated on `ActionMailer::DeliveryJob` because ActionMailer uses a custom class, `ActionMailer::DeliveryJob`, which inherits from `ActiveJob::Base`, rather than your applications `ApplicationJob`.
295
+
296
+ You can use an initializer to configure `ActionMailer::DeliveryJob`, for example:
227
297
 
228
298
  ```ruby
229
299
  # config/initializers/good_job.rb
@@ -238,14 +308,14 @@ rescue StandardError => e
238
308
  end
239
309
  ```
240
310
 
241
- #### Timeouts
311
+ ### Timeouts
242
312
 
243
313
  Job timeouts can be configured with an `around_perform`:
244
314
 
245
315
  ```ruby
246
- class ApplicationJob < ActiveJob::Base
316
+ class ApplicationJob < ActiveJob::Base
247
317
  JobTimeoutError = Class.new(StandardError)
248
-
318
+
249
319
  around_perform do |_job, block|
250
320
  # Timeout jobs after 10 minutes
251
321
  Timeout.timeout(10.minutes, JobTimeoutError) do
@@ -255,20 +325,61 @@ class ApplicationJob < ActiveJob::Base
255
325
  end
256
326
  ```
257
327
 
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:
328
+ ### Optimize queues, threads, and processes
329
+
330
+ 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:
331
+
332
+ - Multiple execution pools within a single process:
261
333
 
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`)
334
+ ```bash
335
+ $ bundle exec good_job --queues=transactional_messages:2;batch_processing:1;-transactional_messages,batch_processing:2;* --max-threads=5
336
+ ```
337
+
338
+ 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 (`:`)
339
+
340
+ - `transactional_messages:2`: execute jobs enqueued on `transactional_messages` with up to 2 threads.
341
+ - `batch_processing:1` execute jobs enqueued on `batch_processing` with a single thread.
342
+ - `-transactional_messages,batch_processing`: execute jobs enqueued on _any_ queue _excluding_ `transactional_messages` or `batch_processing` with up to 2 threads.
343
+ - `*`: execute jobs on any queue on up to 5 threads, as configured by `--max-threads=5`
344
+
345
+ For moderate workloads, multiple isolated thread execution pools offers a good balance between congestion management and economy.
346
+
347
+ Configuration can be injected by environment variables too:
348
+
349
+ ```bash
350
+ $ GOOD_JOB_QUEUES="transactional_messages:2;batch_processing:1;-transactional_messages,batch_processing:2;*" GOOD_JOB_MAX_THREADS=5 bundle exec good_job
351
+ ```
352
+
353
+ - Multiple processes; for example, on Heroku:
354
+
355
+ ```procfile
356
+ # Procfile
357
+
358
+ # Separate dyno types
359
+ worker: bundle exec good_job --max-threads=5
360
+ transactional_worker: bundle exec good_job --queues=transactional_messages --max-threads=2
361
+ batch_worker: bundle exec good_job --queues=batch_processing --max-threads=1
362
+
363
+ # Combined multi-process dyno
364
+ 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
365
+ ```
366
+
367
+ Running multiple processes can optimize for CPU performance at the expense of greater memory and system resource usage.
368
+
369
+ 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 👍
370
+
371
+ ### Database connections
372
+
373
+ 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:
374
+
375
+ ```yaml
376
+ # config/database.yml
377
+ pool: <%= [ENV.fetch("RAILS_MAX_THREADS", 5).to_i, ENV.fetch("GOOD_JOB_MAX_THREADS", 4).to_i].max %>
378
+ ```
268
379
 
269
380
  ### Executing jobs async / in-process
270
381
 
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:
382
+ 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
383
 
273
384
  - Directly configure the ActiveJob adapter:
274
385
 
@@ -276,12 +387,13 @@ GoodJob is able to run "async" in the same process as the webserver (e.g. `bin/r
276
387
  # config/environments/production.rb
277
388
  config.active_job.queue_adapter = GoodJob::Adapter.new(execution_mode: :async, max_threads: 4, poll_interval: 30)
278
389
  ```
390
+
279
391
  - Or, when using `...queue_adapter = :good_job`, via environment variables:
280
392
 
281
393
  ```bash
282
394
  $ GOOD_JOB_EXECUTION_MODE=async GOOD_JOB_MAX_THREADS=4 GOOD_JOB_POLL_INTERVAL=30 bin/rails server
283
395
  ```
284
-
396
+
285
397
  Depending on your application configuration, you may need to take additional steps:
286
398
 
287
399
  - Ensure that you have enough database connections for both web and job execution threads:
@@ -295,27 +407,27 @@ Depending on your application configuration, you may need to take additional ste
295
407
 
296
408
  ```ruby
297
409
  # config/puma.rb
298
-
410
+
299
411
  before_fork do
300
412
  GoodJob.shutdown
301
413
  end
302
-
414
+
303
415
  on_worker_boot do
304
416
  GoodJob.restart
305
417
  end
306
-
418
+
307
419
  on_worker_shutdown do
308
420
  GoodJob.shutdown
309
421
  end
310
-
422
+
311
423
  MAIN_PID = Process.pid
312
424
  at_exit do
313
425
  GoodJob.shutdown if Process.pid == MAIN_PID
314
426
  end
315
427
  ```
316
-
428
+
317
429
  GoodJob is compatible with Puma's `preload_app!` method.
318
-
430
+
319
431
  ### Migrating to GoodJob from a different ActiveJob backend
320
432
 
321
433
  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.
@@ -331,7 +443,7 @@ If your application is already using an ActiveJob backend, you will need to inst
331
443
  ```
332
444
 
333
445
  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
-
446
+
335
447
  ```procfile
336
448
  # Procfile
337
449
  # ...
@@ -344,7 +456,7 @@ If your application is already using an ActiveJob backend, you will need to inst
344
456
 
345
457
  GoodJob is fully instrumented with [`ActiveSupport::Notifications`](https://edgeguides.rubyonrails.org/active_support_instrumentation.html#introduction-to-instrumentation).
346
458
 
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`).
459
+ 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
460
 
349
461
  To preserve job records for later inspection, set an initializer:
350
462
 
@@ -356,7 +468,7 @@ GoodJob.preserve_job_records = true
356
468
  It is also necessary to delete these preserved jobs from the database after a certain time period:
357
469
 
358
470
  - For example, in a Rake task:
359
-
471
+
360
472
  ```ruby
361
473
  GoodJob::Job.finished(1.day.ago).delete_all
362
474
  ```
@@ -426,7 +538,7 @@ $ gem signin
426
538
  # Update version number, changelog, and create git commit:
427
539
  $ bundle exec rake release[minor] # major,minor,patch
428
540
 
429
- # ..and follow subsequent directions.
541
+ # ..and follow subsequent directions.
430
542
  ```
431
543
 
432
544
  ## License
@@ -8,7 +8,6 @@ require 'good_job/job'
8
8
  require 'good_job/scheduler'
9
9
  require 'good_job/multi_scheduler'
10
10
  require 'good_job/adapter'
11
- require 'good_job/pg_locks'
12
11
  require 'good_job/performer'
13
12
  require 'good_job/current_execution'
14
13
  require 'good_job/notifier'
@@ -4,17 +4,29 @@ module GoodJob
4
4
  class CLI < Thor
5
5
  RAILS_ENVIRONMENT_RB = File.expand_path("config/environment.rb")
6
6
 
7
- desc :start, "Start job worker"
7
+ desc :start, <<~DESCRIPTION
8
+ Executes queued jobs.
9
+
10
+ All options can be configured with environment variables.
11
+ See option descriptions for the matching environment variable name.
12
+
13
+ == Configuring queues
14
+ Separate multiple queues with commas; exclude queues with a leading minus;
15
+ separate isolated execution pools with semicolons and threads with colons.
16
+
17
+ DESCRIPTION
8
18
  method_option :max_threads,
9
19
  type: :numeric,
10
- desc: "Maximum number of threads to use for working jobs (default: ActiveRecord::Base.connection_pool.size)"
20
+ banner: 'COUNT',
21
+ desc: "Maximum number of threads to use for working jobs. (env var: GOOD_JOB_MAX_THREADS, default: 5)"
11
22
  method_option :queues,
12
23
  type: :string,
13
- banner: "queue1,queue2(;queue3,queue4:5;-queue1,queue2)",
14
- desc: "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: *)"
24
+ banner: "QUEUE_LIST",
25
+ desc: "Queues to work from. (env var: GOOD_JOB_QUEUES, default: *)"
15
26
  method_option :poll_interval,
16
27
  type: :numeric,
17
- desc: "Interval between polls for available jobs in seconds (default: 1)"
28
+ banner: 'SECONDS',
29
+ desc: "Interval between polls for available jobs in seconds (env var: GOOD_JOB_POLL_INTERVAL, default: 1)"
18
30
  def start
19
31
  set_up_application!
20
32
 
@@ -39,17 +51,35 @@ module GoodJob
39
51
 
40
52
  default_task :start
41
53
 
42
- desc :cleanup_preserved_jobs, "Delete preserved job records"
54
+ desc :cleanup_preserved_jobs, <<~DESCRIPTION
55
+ Deletes preserved job records.
56
+
57
+ By default, GoodJob deletes job records when the job is performed and this
58
+ command is not necessary.
59
+
60
+ However, when `GoodJob.preserve_job_records = true`, the jobs will be
61
+ preserved in the database. This is useful when wanting to analyze or
62
+ inspect job performance.
63
+
64
+ If you are preserving job records this way, use this command regularly
65
+ to delete old records and preserve space in your database.
66
+
67
+ DESCRIPTION
43
68
  method_option :before_seconds_ago,
44
69
  type: :numeric,
45
- default: 24 * 60 * 60,
46
- desc: "Delete records finished more than this many seconds ago"
47
-
70
+ banner: 'SECONDS',
71
+ desc: "Delete records finished more than this many seconds ago (env var: GOOD_JOB_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO, default: 86400)"
48
72
  def cleanup_preserved_jobs
49
73
  set_up_application!
50
74
 
51
- timestamp = Time.current - options[:before_seconds_ago]
52
- ActiveSupport::Notifications.instrument("cleanup_preserved_jobs.good_job", { before_seconds_ago: options[:before_seconds_ago], timestamp: timestamp }) do |payload|
75
+ configuration = GoodJob::Configuration.new(options)
76
+
77
+ timestamp = Time.current - configuration.cleanup_preserved_jobs_before_seconds_ago
78
+
79
+ ActiveSupport::Notifications.instrument(
80
+ "cleanup_preserved_jobs.good_job",
81
+ { before_seconds_ago: configuration.cleanup_preserved_jobs_before_seconds_ago, timestamp: timestamp }
82
+ ) do |payload|
53
83
  deleted_records_count = GoodJob::Job.finished(timestamp).delete_all
54
84
 
55
85
  payload[:deleted_records_count] = deleted_records_count
@@ -51,5 +51,13 @@ module GoodJob
51
51
  1
52
52
  ).to_i
53
53
  end
54
+
55
+ def cleanup_preserved_jobs_before_seconds_ago
56
+ (
57
+ options[:before_seconds_ago] ||
58
+ env['GOOD_JOB_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO'] ||
59
+ 24 * 60 * 60
60
+ ).to_i
61
+ end
54
62
  end
55
63
  end
@@ -25,8 +25,8 @@ module GoodJob
25
25
  join_sql = <<~SQL
26
26
  LEFT JOIN pg_locks ON pg_locks.locktype = 'advisory'
27
27
  AND pg_locks.objsubid = 1
28
- AND pg_locks.classid = ('x'||substr(md5(:table_name || "#{table_name}"."#{primary_key}"::text), 1, 16))::bit(32)::int
29
- AND pg_locks.objid = (('x'||substr(md5(:table_name || "#{table_name}"."#{primary_key}"::text), 1, 16))::bit(64) << 32)::bit(32)::int
28
+ AND pg_locks.classid = ('x'||substr(md5(:table_name || #{quoted_table_name}.#{quoted_primary_key}::text), 1, 16))::bit(32)::int
29
+ AND pg_locks.objid = (('x'||substr(md5(:table_name || #{quoted_table_name}.#{quoted_primary_key}::text), 1, 16))::bit(64) << 32)::bit(32)::int
30
30
  SQL
31
31
 
32
32
  joins(sanitize_sql_for_conditions([join_sql, { table_name: table_name }]))
@@ -1,3 +1,3 @@
1
1
  module GoodJob
2
- VERSION = '1.2.3'.freeze
2
+ VERSION = '1.2.4'.freeze
3
3
  end
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: 1.2.3
4
+ version: 1.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-27 00:00:00.000000000 Z
11
+ date: 2020-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -178,6 +178,48 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: kramdown
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: kramdown-parser-gfm
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: mdl
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ">="
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
181
223
  - !ruby/object:Gem::Dependency
182
224
  name: pry-rails
183
225
  requirement: !ruby/object:Gem::Requirement
@@ -347,7 +389,6 @@ files:
347
389
  - lib/good_job/multi_scheduler.rb
348
390
  - lib/good_job/notifier.rb
349
391
  - lib/good_job/performer.rb
350
- - lib/good_job/pg_locks.rb
351
392
  - lib/good_job/railtie.rb
352
393
  - lib/good_job/scheduler.rb
353
394
  - lib/good_job/version.rb
@@ -1,21 +0,0 @@
1
- module GoodJob
2
- class PgLocks < ActiveRecord::Base
3
- self.table_name = 'pg_locks'.freeze
4
-
5
- # https://www.postgresql.org/docs/9.6/view-pg-locks.html
6
- # Advisory locks can be acquired on keys consisting of either a single bigint value or two integer values.
7
- # A bigint key is displayed with its high-order half in the classid column, its low-order half in the objid column, and objsubid equal to 1.
8
- # The original bigint value can be reassembled with the expression (classid::bigint << 32) | objid::bigint.
9
- # Integer keys are displayed with the first key in the classid column, the second key in the objid column, and objsubid equal to 2.
10
- # The actual meaning of the keys is up to the user. Advisory locks are local to each database, so the database column is meaningful for an advisory lock.
11
- def self.advisory_lock_details
12
- connection.select <<~SQL
13
- SELECT *
14
- FROM pg_locks
15
- WHERE
16
- locktype = 'advisory' AND
17
- objsubid = 1
18
- SQL
19
- end
20
- end
21
- end