good_job 3.1.0 → 3.2.0

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: bc6e3cffa2189a101181b7ceb278de97ded27d14dd6da915ea8fe3729907dd88
4
- data.tar.gz: 0504d2f2efd09d1d52669597e364f62b69edc739d3c76b8bcfdd1933ea7cb8da
3
+ metadata.gz: 9ecbb75f2764a72686acb96367389abb1900321b5cf1292d6522aa8094c68451
4
+ data.tar.gz: 43a5305a9f2610c1544d6e52c61f0b338771b07d92d6493fed0058ad33bbc045
5
5
  SHA512:
6
- metadata.gz: c10f675a3635f481e370502828ed0902aff3464e19f161bf5f300463a2671ecac09643eb0943030eda30163171b67986b0f9e31ca423ad5da9e4ffd5b23a7df7
7
- data.tar.gz: 3ab12e91adb910040a4007140054cc048a0f83e34e54ee649e52ea673a27b95cfb267b56fae98a7605616e4c3f55d17af403c99bf9ba2a5d504dffdd917a7cbb
6
+ metadata.gz: 0e637579c190a3f3d1aba6c02f6a71e2193d9e5c4bb449a3d4d9571093150a25a1c293ac3f5c541d2fae09aeffff771692fa7ef58bc8ed672f61a2c9d35a7e74
7
+ data.tar.gz: bc669b4d1628f7ff4b885787c65a38a57ad020aa168c3ae85f0c6bb26c9f0e19b64947682b0c99cf3eb28c2d660e1d79ee6095000a72340f09229d1679fa5dfe
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [v3.2.0](https://github.com/bensheldon/good_job/tree/v3.2.0) (2022-07-12)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.1.0...v3.2.0)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Ordered queue handling by workers [\#665](https://github.com/bensheldon/good_job/pull/665) ([jrochkind](https://github.com/jrochkind))
10
+
3
11
  ## [v3.1.0](https://github.com/bensheldon/good_job/tree/v3.1.0) (2022-07-11)
4
12
 
5
13
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.0.2...v3.1.0)
data/README.md CHANGED
@@ -665,7 +665,7 @@ By default, GoodJob creates a single thread execution pool that will execute job
665
665
 
666
666
  A pool is configured with the following syntax `<participating_queues>:<thread_count>`:
667
667
 
668
- - `<participating_queues>`: either `queue1,queue2` (only those queues), `*` (all) or `-queue1,queue2` (all except those queues).
668
+ - `<participating_queues>`: either `queue1,queue2` (only those queues), `+queue1,queue2` (only those queues, and processed in order), `*` (all) or `-queue1,queue2` (all except those queues).
669
669
  - `<thread_count>`: a count overriding for this specific pool the global `max-threads`.
670
670
 
671
671
  Pool configurations are separated with a semicolon (;) in the `queues` configuration
@@ -683,6 +683,12 @@ By default, GoodJob creates a single thread execution pool that will execute job
683
683
  - `-transactional_messages,batch_processing`: execute jobs enqueued on _any_ queue _excluding_ `transactional_messages` or `batch_processing`, with up to 2 threads.
684
684
  - `*`: execute jobs on any queue, with up to 5 threads (as configured by `--max-threads=5`).
685
685
 
686
+ When a pool is performing jobs from multiple queues, jobs will be performed from specified queues, ordered by priority and creation time. To perform jobs from queues in the queues' given order, use the `+` modifier. In this example, jobs in `batch_processing` will be performed only when there are no jobs in `transactional_messages`:
687
+
688
+ ```bash
689
+ bundle exec good_job --queues="+transactional_messages,batch_processing"
690
+ ```
691
+
686
692
  Configuration can be injected by environment variables too:
687
693
 
688
694
  ```bash
@@ -24,7 +24,7 @@ module GoodJob
24
24
  # Perform the next eligible job
25
25
  # @return [Object, nil] Returns job result or +nil+ if no job was found
26
26
  def next
27
- job_query.perform_with_advisory_lock
27
+ job_query.perform_with_advisory_lock(parsed_queues: parsed_queues)
28
28
  end
29
29
 
30
30
  # Tests whether this performer should be used in GoodJob's current state.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '3.1.0'
4
+ VERSION = '3.2.0'
5
5
  end
@@ -29,15 +29,21 @@ module GoodJob
29
29
  # not match.
30
30
  # - +{ include: Array<String> }+ indicates the listed queue names should
31
31
  # match.
32
+ # - +{ include: Array<String>, ordered_queues: true }+ indicates the listed
33
+ # queue names should match, and dequeue should respect queue order.
32
34
  # @example
33
35
  # GoodJob::Execution.queue_parser('-queue1,queue2')
34
36
  # => { exclude: [ 'queue1', 'queue2' ] }
35
37
  def self.queue_parser(string)
36
38
  string = string.presence || '*'
37
39
 
38
- if string.first == '-'
40
+ case string.first
41
+ when '-'
39
42
  exclude_queues = true
40
43
  string = string[1..-1]
44
+ when '+'
45
+ ordered_queues = true
46
+ string = string[1..-1]
41
47
  end
42
48
 
43
49
  queues = string.split(',').map(&:strip)
@@ -46,6 +52,11 @@ module GoodJob
46
52
  { all: true }
47
53
  elsif exclude_queues
48
54
  { exclude: queues }
55
+ elsif ordered_queues
56
+ {
57
+ include: queues,
58
+ ordered_queues: true,
59
+ }
49
60
  else
50
61
  { include: queues }
51
62
  end
@@ -95,10 +106,34 @@ module GoodJob
95
106
  scope :creation_ordered, -> { order('created_at ASC') }
96
107
 
97
108
  # Order jobs for de-queueing
98
- # @!method dequeue_ordered
109
+ # @!method dequeueing_ordered
99
110
  # @!scope class
100
- # @return [ActiveRecord:Relation]
101
- scope :dequeue_ordered, -> { priority_ordered.creation_ordered }
111
+ # @param parsed_queues [Hash]
112
+ # optional output of .queue_parser, parsed queues, will be used for
113
+ # ordered queues.
114
+ # @return [ActiveRecord::Relation]
115
+ scope :dequeueing_ordered, (lambda do |parsed_queues|
116
+ relation = self
117
+ relation = relation.queue_ordered(parsed_queues[:include]) if parsed_queues && parsed_queues[:ordered_queues] && parsed_queues[:include]
118
+ relation = relation.priority_ordered.creation_ordered
119
+
120
+ relation
121
+ end)
122
+
123
+ # Order jobs in order of queues in array param
124
+ # @!method queue_ordered
125
+ # @!scope class
126
+ # @param queues [Array<string] ordered names of queues
127
+ # @return [ActiveRecord::Relation]
128
+ scope :queue_ordered, (lambda do |queues|
129
+ clauses = queues.map.with_index do |queue_name, index|
130
+ "WHEN queue_name = '#{queue_name}' THEN #{index}"
131
+ end
132
+
133
+ order(
134
+ Arel.sql("(CASE #{clauses.join(' ')} ELSE #{queues.length} END)")
135
+ )
136
+ end)
102
137
 
103
138
  # Order jobs by scheduled or created (oldest first).
104
139
  # @!method schedule_ordered
@@ -165,8 +200,8 @@ module GoodJob
165
200
  # return value for the job's +#perform+ method, and the exception the job
166
201
  # raised, if any (if the job raised, then the second array entry will be
167
202
  # +nil+). If there were no jobs to execute, returns +nil+.
168
- def self.perform_with_advisory_lock
169
- unfinished.dequeue_ordered.only_scheduled.limit(1).with_advisory_lock(unlock_session: true) do |executions|
203
+ def self.perform_with_advisory_lock(parsed_queues: nil)
204
+ unfinished.dequeueing_ordered(parsed_queues).only_scheduled.limit(1).with_advisory_lock(unlock_session: true) do |executions|
170
205
  execution = executions.first
171
206
  break if execution.blank?
172
207
  break :unlocked unless execution&.executable?
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.1.0
4
+ version: 3.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Sheldon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-07-11 00:00:00.000000000 Z
11
+ date: 2022-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob