good_job 3.4.1 → 3.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +49 -2
- data/README.md +8 -3
- data/app/models/good_job/cron_entry.rb +3 -1
- data/app/views/good_job/shared/_filter.erb +1 -0
- data/lib/good_job/active_job_extensions/concurrency.rb +23 -10
- data/lib/good_job/log_subscriber.rb +4 -4
- data/lib/good_job/version.rb +1 -1
- metadata +2 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c54a7908e5803c8f247421375b0ca4a09f97d5b0d21131ef2bfc54e91a4c7eed
|
4
|
+
data.tar.gz: 8a616c9407d2844ee89e2f12fa71c197ddb60e693983c66ce664ac413d0676f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0040cd9afa69d73d4c9bf09da90bd7c1e4c73d4dc4251faff13fd495e2c39d081d099163482edb332a392be1dd560ac056705a5261363e8172d2ae7eab20be55
|
7
|
+
data.tar.gz: c4e41bd8da8e2afd309fceb2c0c5eb4b042d85234c4d34f4a687bcb2fe63f9e2f7d0c442c07bf68a248201d5e9c42c2e84dc8022c9f3eace8ea0b97c3995e004
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,54 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v3.4.4](https://github.com/bensheldon/good_job/tree/v3.4.4) (2022-08-20)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.4.3...v3.4.4)
|
6
|
+
|
7
|
+
**Fixed bugs:**
|
8
|
+
|
9
|
+
- Keep locale param when submitting dashboard filter [\#707](https://github.com/bensheldon/good_job/pull/707) ([aki77](https://github.com/aki77))
|
10
|
+
|
11
|
+
**Merged pull requests:**
|
12
|
+
|
13
|
+
- Fix document [\#704](https://github.com/bensheldon/good_job/pull/704) ([aki77](https://github.com/aki77))
|
14
|
+
- Describe pessimistic usecases [\#702](https://github.com/bensheldon/good_job/pull/702) ([shouichi](https://github.com/shouichi))
|
15
|
+
|
16
|
+
## [v3.4.3](https://github.com/bensheldon/good_job/tree/v3.4.3) (2022-08-15)
|
17
|
+
|
18
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.4.2...v3.4.3)
|
19
|
+
|
20
|
+
**Closed issues:**
|
21
|
+
|
22
|
+
- How to run multiple workers? [\#699](https://github.com/bensheldon/good_job/issues/699)
|
23
|
+
- Getting Postgres Errors on killing development server after setting up Goodjob [\#692](https://github.com/bensheldon/good_job/issues/692)
|
24
|
+
|
25
|
+
**Merged pull requests:**
|
26
|
+
|
27
|
+
- Fix Project v2 GitHub Actions [\#701](https://github.com/bensheldon/good_job/pull/701) ([bensheldon](https://github.com/bensheldon))
|
28
|
+
- Remove development dependencies: memory\_profiler, rbtrace, sigdump [\#700](https://github.com/bensheldon/good_job/pull/700) ([bensheldon](https://github.com/bensheldon))
|
29
|
+
- Allow concurrency limits to be configured dynamically with lambda/proc [\#696](https://github.com/bensheldon/good_job/pull/696) ([baka-san](https://github.com/baka-san))
|
30
|
+
- Add additional details to Concurrency Control explanation [\#695](https://github.com/bensheldon/good_job/pull/695) ([bensheldon](https://github.com/bensheldon))
|
31
|
+
|
32
|
+
## [v3.4.2](https://github.com/bensheldon/good_job/tree/v3.4.2) (2022-08-13)
|
33
|
+
|
34
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.4.1...v3.4.2)
|
35
|
+
|
36
|
+
**Fixed bugs:**
|
37
|
+
|
38
|
+
- Jobs enqueued via dashboard ignores app default\_locale [\#697](https://github.com/bensheldon/good_job/issues/697)
|
39
|
+
- Include better exception log messages, including class and backtrace [\#693](https://github.com/bensheldon/good_job/pull/693) ([bensheldon](https://github.com/bensheldon))
|
40
|
+
|
41
|
+
**Closed issues:**
|
42
|
+
|
43
|
+
- Do we need to implement concurrency with scheduled cron jobs? [\#690](https://github.com/bensheldon/good_job/issues/690)
|
44
|
+
- Uninitialized constant GoodJob::JobsController [\#674](https://github.com/bensheldon/good_job/issues/674)
|
45
|
+
- ActiveRecord::StatementInvalid: PG::ConnectionBad: PQsocket\(\) can't get socket descriptor every 30 minutes aprox. [\#579](https://github.com/bensheldon/good_job/issues/579)
|
46
|
+
- Handle assets in dashboard when rails app is behind proxy path [\#424](https://github.com/bensheldon/good_job/issues/424)
|
47
|
+
|
48
|
+
**Merged pull requests:**
|
49
|
+
|
50
|
+
- Enqueues Cron jobs with I18n default locale [\#698](https://github.com/bensheldon/good_job/pull/698) ([esasse](https://github.com/esasse))
|
51
|
+
|
3
52
|
## [v3.4.1](https://github.com/bensheldon/good_job/tree/v3.4.1) (2022-08-06)
|
4
53
|
|
5
54
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v3.4.0...v3.4.1)
|
@@ -8,7 +57,6 @@
|
|
8
57
|
|
9
58
|
- Add `cron_enabled` to Process state [\#673](https://github.com/bensheldon/good_job/issues/673)
|
10
59
|
- Good job is using a lot of memory / ram [\#613](https://github.com/bensheldon/good_job/issues/613)
|
11
|
-
- ActiveRecord::StatementInvalid: PG::ConnectionBad: PQsocket\(\) can't get socket descriptor every 30 minutes aprox. [\#579](https://github.com/bensheldon/good_job/issues/579)
|
12
60
|
|
13
61
|
**Merged pull requests:**
|
14
62
|
|
@@ -90,7 +138,6 @@
|
|
90
138
|
|
91
139
|
**Closed issues:**
|
92
140
|
|
93
|
-
- Calculating database connections [\#669](https://github.com/bensheldon/good_job/issues/669)
|
94
141
|
- Unable to Replace GoodJob's Logger [\#667](https://github.com/bensheldon/good_job/issues/667)
|
95
142
|
- Readme should consistently encourage usage of `config.good_job....` instead of `GoodJob.` configuration [\#628](https://github.com/bensheldon/good_job/issues/628)
|
96
143
|
- Improve the "Gem development" section of README? [\#551](https://github.com/bensheldon/good_job/issues/551)
|
data/README.md
CHANGED
@@ -283,7 +283,7 @@ Available configuration options are:
|
|
283
283
|
- `inline_execution_respects_schedule` (boolean) Opt-in to future behavior of inline execution respecting scheduled jobs. Defaults to `false`.
|
284
284
|
- `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` (Default: `Rails.logger`).
|
285
285
|
- `preserve_job_records` (boolean) keeps job records in your database even after jobs are completed. (Default: `true`)
|
286
|
-
- `retry_on_unhandled_error` (boolean) causes jobs to be re-queued and retried if they raise an instance of `StandardError`. Be advised this may lead to jobs being repeated infinitely ([see below for more on retries](#retries)). Instances of `Exception`, like SIGINT, will *always* be retried, regardless of this attribute’s value. (Default: `
|
286
|
+
- `retry_on_unhandled_error` (boolean) causes jobs to be re-queued and retried if they raise an instance of `StandardError`. Be advised this may lead to jobs being repeated infinitely ([see below for more on retries](#retries)). Instances of `Exception`, like SIGINT, will *always* be retried, regardless of this attribute’s value. (Default: `false`)
|
287
287
|
- `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. Example:
|
288
288
|
|
289
289
|
```ruby
|
@@ -406,15 +406,18 @@ class MyJob < ApplicationJob
|
|
406
406
|
|
407
407
|
good_job_control_concurrency_with(
|
408
408
|
# Maximum number of unfinished jobs to allow with the concurrency key
|
409
|
+
# Can be an Integer or Lambda/Proc that is invoked in the context of the job
|
409
410
|
total_limit: 1,
|
410
411
|
|
411
412
|
# Or, if more control is needed:
|
412
413
|
# Maximum number of jobs with the concurrency key to be
|
413
414
|
# concurrently enqueued (excludes performing jobs)
|
415
|
+
# Can be an Integer or Lambda/Proc that is invoked in the context of the job
|
414
416
|
enqueue_limit: 2,
|
415
417
|
|
416
418
|
# Maximum number of jobs with the concurrency key to be
|
417
419
|
# concurrently performed (excludes enqueued jobs)
|
420
|
+
# Can be an Integer or Lambda/Proc that is invoked in the context of the job
|
418
421
|
perform_limit: 1,
|
419
422
|
|
420
423
|
# Note: Under heavy load, the total number of jobs may exceed the
|
@@ -444,10 +447,12 @@ job.good_job_concurrency_key #=> "Unique-Alice"
|
|
444
447
|
|
445
448
|
#### How concurrency controls work
|
446
449
|
|
447
|
-
GoodJob's concurrency control strategy for `perform_limit` is "optimistic retry with an incremental backoff".
|
450
|
+
GoodJob's concurrency control strategy for `perform_limit` is "optimistic retry with an incremental backoff". The [code is readable](https://github.com/bensheldon/good_job/blob/main/lib/good_job/active_job_extensions/concurrency.rb).
|
448
451
|
|
449
|
-
- "Optimistic" meaning that the implementation's performance trade-off assumes that collisions are atypical (e.g. two users enqueue the same job at the same time) rather than regular (e.g. the system enqueues thousands of colliding jobs at the same time).
|
452
|
+
- "Optimistic" meaning that the implementation's performance trade-off assumes that collisions are atypical (e.g. two users enqueue the same job at the same time) rather than regular (e.g. the system enqueues thousands of colliding jobs at the same time). Depending on your concurrency requirements, you may also want to manage concurrency through the number of GoodJob threads and processes that are performing a given queue.
|
450
453
|
- "Retry with an incremental backoff" means that when `perform_limit` is exceeded, the job will raise a `GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError` which is caught by a `retry_on` handler which re-schedules the job to execute in the near future with an incremental backoff.
|
454
|
+
- First-in-first-out job execution order is not preserved when a job is retried with incremental back-off.
|
455
|
+
- For pessimistic usecases that collisions are expected, use number of threads/processes (e.g., `good_job --queue "serial:1;-serial:5"`) to control concurrency. It is also a good idea to use `perform_limit` as backstop.
|
451
456
|
|
452
457
|
### Cron-style repeating/recurring jobs
|
453
458
|
|
@@ -106,7 +106,9 @@ module GoodJob # :nodoc:
|
|
106
106
|
current_thread.cron_at = cron_at
|
107
107
|
|
108
108
|
configured_job = job_class.constantize.set(set_value)
|
109
|
-
|
109
|
+
I18n.with_locale(I18n.default_locale) do
|
110
|
+
kwargs_value.present? ? configured_job.perform_later(*args_value, **kwargs_value) : configured_job.perform_later(*args_value)
|
111
|
+
end
|
110
112
|
end
|
111
113
|
rescue ActiveRecord::RecordNotUnique
|
112
114
|
false
|
@@ -5,6 +5,7 @@
|
|
5
5
|
<%= form_with(url: "", method: :get, local: true, id: "filter_form", class: "container-fluid") do |form| %>
|
6
6
|
<%= hidden_field_tag :poll, params[:poll] %>
|
7
7
|
<%= hidden_field_tag :state, params[:state] %>
|
8
|
+
<%= hidden_field_tag :locale, params[:locale] if params[:locale] %>
|
8
9
|
<div class="d-flex flex-row w-100">
|
9
10
|
<div class="me-2">
|
10
11
|
<select name="queue_name" id="job_queue_filter" class="form-select form-select-sm">
|
@@ -31,11 +31,17 @@ module GoodJob
|
|
31
31
|
next(block.call) if CurrentThread.active_job_id == job.job_id
|
32
32
|
|
33
33
|
enqueue_limit = job.class.good_job_concurrency_config[:enqueue_limit]
|
34
|
-
|
34
|
+
enqueue_limit = instance_exec(&enqueue_limit) if enqueue_limit.respond_to?(:call)
|
35
|
+
enqueue_limit = nil unless enqueue_limit.present? && (0...Float::INFINITY).cover?(enqueue_limit)
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
unless enqueue_limit
|
38
|
+
total_limit = job.class.good_job_concurrency_config[:total_limit]
|
39
|
+
total_limit = instance_exec(&total_limit) if total_limit.respond_to?(:call)
|
40
|
+
total_limit = nil unless total_limit.present? && (0...Float::INFINITY).cover?(total_limit)
|
41
|
+
end
|
42
|
+
|
43
|
+
limit = enqueue_limit || total_limit
|
44
|
+
next(block.call) unless limit
|
39
45
|
|
40
46
|
# Only generate the concurrency key on the initial enqueue in case it is dynamic
|
41
47
|
job.good_job_concurrency_key ||= job._good_job_concurrency_key
|
@@ -50,7 +56,7 @@ module GoodJob
|
|
50
56
|
end
|
51
57
|
|
52
58
|
# The job has not yet been enqueued, so check if adding it will go over the limit
|
53
|
-
block.call unless enqueue_concurrency + 1 >
|
59
|
+
block.call unless (enqueue_concurrency + 1) > limit
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
@@ -64,11 +70,18 @@ module GoodJob
|
|
64
70
|
# Don't attempt to enforce concurrency limits with other queue adapters.
|
65
71
|
next unless job.class.queue_adapter.is_a?(GoodJob::Adapter)
|
66
72
|
|
67
|
-
perform_limit = job.class.good_job_concurrency_config[:perform_limit]
|
68
|
-
|
73
|
+
perform_limit = job.class.good_job_concurrency_config[:perform_limit]
|
74
|
+
perform_limit = instance_exec(&perform_limit) if perform_limit.respond_to?(:call)
|
75
|
+
perform_limit = nil unless perform_limit.present? && (0...Float::INFINITY).cover?(perform_limit)
|
76
|
+
|
77
|
+
unless perform_limit
|
78
|
+
total_limit = job.class.good_job_concurrency_config[:total_limit]
|
79
|
+
total_limit = instance_exec(&total_limit) if total_limit.respond_to?(:call)
|
80
|
+
total_limit = nil unless total_limit.present? && (0...Float::INFINITY).cover?(total_limit)
|
81
|
+
end
|
69
82
|
|
70
|
-
|
71
|
-
next unless
|
83
|
+
limit = perform_limit || total_limit
|
84
|
+
next unless limit
|
72
85
|
|
73
86
|
key = job.good_job_concurrency_key
|
74
87
|
next if key.blank?
|
@@ -79,7 +92,7 @@ module GoodJob
|
|
79
92
|
end
|
80
93
|
|
81
94
|
GoodJob::Execution.advisory_lock_key(key, function: "pg_advisory_lock") do
|
82
|
-
allowed_active_job_ids = GoodJob::Execution.unfinished.where(concurrency_key: key).advisory_locked.order(Arel.sql("COALESCE(performed_at, scheduled_at, created_at) ASC")).limit(
|
95
|
+
allowed_active_job_ids = GoodJob::Execution.unfinished.where(concurrency_key: key).advisory_locked.order(Arel.sql("COALESCE(performed_at, scheduled_at, created_at) ASC")).limit(limit).pluck(:active_job_id)
|
83
96
|
# The current job has already been locked and will appear in the previous query
|
84
97
|
raise GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError unless allowed_active_job_ids.include? job.job_id
|
85
98
|
end
|
@@ -32,7 +32,7 @@ module GoodJob
|
|
32
32
|
return unless exception
|
33
33
|
|
34
34
|
error do
|
35
|
-
"GoodJob error: #{exception}\n #{exception.backtrace}"
|
35
|
+
"GoodJob error: #{exception.class}: #{exception}\n #{exception.backtrace}"
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -42,7 +42,7 @@ module GoodJob
|
|
42
42
|
return unless exception
|
43
43
|
|
44
44
|
error do
|
45
|
-
"GoodJob error: #{exception}\n #{exception.backtrace}"
|
45
|
+
"GoodJob error: #{exception.class}: #{exception}\n #{exception.backtrace}"
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -123,10 +123,10 @@ module GoodJob
|
|
123
123
|
|
124
124
|
# @!macro notification_responder
|
125
125
|
def notifier_notify_error(event)
|
126
|
-
|
126
|
+
exception = event.payload[:error]
|
127
127
|
|
128
128
|
error do
|
129
|
-
"Notifier errored: #{
|
129
|
+
"Notifier errored: #{exception.class}: #{exception}\n #{exception.backtrace}"
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
data/lib/good_job/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: good_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.4.
|
4
|
+
version: 3.4.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: 2022-08-
|
11
|
+
date: 2022-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -290,20 +290,6 @@ dependencies:
|
|
290
290
|
- - ">="
|
291
291
|
- !ruby/object:Gem::Version
|
292
292
|
version: '0'
|
293
|
-
- !ruby/object:Gem::Dependency
|
294
|
-
name: sigdump
|
295
|
-
requirement: !ruby/object:Gem::Requirement
|
296
|
-
requirements:
|
297
|
-
- - ">="
|
298
|
-
- !ruby/object:Gem::Version
|
299
|
-
version: '0'
|
300
|
-
type: :development
|
301
|
-
prerelease: false
|
302
|
-
version_requirements: !ruby/object:Gem::Requirement
|
303
|
-
requirements:
|
304
|
-
- - ">="
|
305
|
-
- !ruby/object:Gem::Version
|
306
|
-
version: '0'
|
307
293
|
- !ruby/object:Gem::Dependency
|
308
294
|
name: yard
|
309
295
|
requirement: !ruby/object:Gem::Requirement
|