shoryuken 3.0.4 → 3.1.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +79 -0
  5. data/Gemfile +1 -0
  6. data/README.md +15 -117
  7. data/bin/cli/base.rb +0 -2
  8. data/bin/cli/sqs.rb +18 -1
  9. data/bin/shoryuken +9 -1
  10. data/examples/default_worker.rb +1 -1
  11. data/lib/shoryuken/default_worker_registry.rb +2 -2
  12. data/lib/shoryuken/environment_loader.rb +33 -13
  13. data/lib/shoryuken/fetcher.rb +17 -16
  14. data/lib/shoryuken/launcher.rb +86 -7
  15. data/lib/shoryuken/manager.rb +42 -72
  16. data/lib/shoryuken/middleware/server/auto_delete.rb +3 -8
  17. data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +4 -4
  18. data/lib/shoryuken/middleware/server/exponential_backoff_retry.rb +8 -2
  19. data/lib/shoryuken/middleware/server/timing.rb +2 -2
  20. data/lib/shoryuken/options.rb +192 -0
  21. data/lib/shoryuken/polling/base.rb +67 -0
  22. data/lib/shoryuken/polling/strict_priority.rb +77 -0
  23. data/lib/shoryuken/polling/weighted_round_robin.rb +66 -0
  24. data/lib/shoryuken/processor.rb +23 -17
  25. data/lib/shoryuken/queue.rb +27 -6
  26. data/lib/shoryuken/runner.rb +3 -15
  27. data/lib/shoryuken/version.rb +1 -1
  28. data/lib/shoryuken/worker.rb +8 -0
  29. data/lib/shoryuken.rb +39 -172
  30. data/shoryuken.gemspec +1 -1
  31. data/spec/integration/launcher_spec.rb +12 -6
  32. data/spec/shoryuken/environment_loader_spec.rb +3 -12
  33. data/spec/shoryuken/fetcher_spec.rb +30 -15
  34. data/spec/shoryuken/manager_spec.rb +12 -13
  35. data/spec/shoryuken/middleware/server/auto_extend_visibility_spec.rb +1 -1
  36. data/spec/shoryuken/middleware/server/exponential_backoff_retry_spec.rb +1 -1
  37. data/spec/shoryuken/options_spec.rb +100 -0
  38. data/spec/shoryuken/{polling_spec.rb → polling/strict_priority_spec.rb} +1 -100
  39. data/spec/shoryuken/polling/weighted_round_robin_spec.rb +99 -0
  40. data/spec/shoryuken/processor_spec.rb +20 -37
  41. data/spec/shoryuken/queue_spec.rb +72 -26
  42. data/spec/shoryuken/runner_spec.rb +3 -4
  43. data/spec/shoryuken_spec.rb +0 -59
  44. data/spec/spec_helper.rb +8 -2
  45. data/test_workers/endless_uninterruptive_worker.rb +1 -1
  46. metadata +14 -7
  47. data/lib/shoryuken/polling.rb +0 -204
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e1367b27e316c258563ef328b78bc64947c849d8
4
- data.tar.gz: 285db9748d737bfe07a6904db381d3c11883cd05
3
+ metadata.gz: 779c3e9c7f708f0a6dccb3e8b0c9f7e2490b25e1
4
+ data.tar.gz: bf260a2793ff8c07ddfb670832ba5f12af8d85d9
5
5
  SHA512:
6
- metadata.gz: 7f85154f339098c0b04a01673548b0c688217290772131dc28a1ed0c378b0cb671576f5a195143d915a8ab70ed836b089bd12ff6c4d6aa78d81bf858729323a6
7
- data.tar.gz: 9b5180a9baf239178c11afcc7f55d31392162deeb95aa7f49836a64e94fcc114b145ba82414b83ad22d278612d3cca53436bb804d41d98ccfbe9f1eea4f678cc
6
+ metadata.gz: 1f3e7a4b668c929daa1b5424b7a8ab7f028238b3f6dfe0e812351991bbc37923b58491760df6e4ed4921624cd4954761daeac257c6a540fd193d160d121044de
7
+ data.tar.gz: 02f2bf2e813cbe1624ae83d16936196ecf523fe8d3773f9b0c39813aa0822d3c71fd273ee01a63072c20d86bf05f4c1a775eda3fae41cec4bf55ea567f772aef
data/.rubocop.yml CHANGED
@@ -32,7 +32,7 @@ Metrics/ParameterLists:
32
32
  Enabled: false
33
33
 
34
34
  Metrics/LineLength:
35
- Max: 120
35
+ Max: 130
36
36
 
37
37
  Metrics/MethodLength :
38
38
  Enabled: false
data/.travis.yml CHANGED
@@ -4,6 +4,7 @@ rvm:
4
4
  - 2.1.0
5
5
  - 2.2.0
6
6
  - 2.3.3
7
+ - 2.4.1
7
8
 
8
9
  notifications:
9
10
  email:
data/CHANGELOG.md CHANGED
@@ -1,4 +1,75 @@
1
+ ## [v3.1.0] - 2017-07-02
2
+
3
+ - Add shoryuken sqs delete command
4
+ - [#395](https://github.com/phstc/shoryuken/pull/395)
5
+
6
+ - Add processing groups support; Concurrency per queue support
7
+ - [#389](https://github.com/phstc/shoryuken/pull/389)
8
+
9
+ - Terminate Shoryuken if the fetcher crashes
10
+ - [#389](https://github.com/phstc/shoryuken/pull/389)
11
+
12
+ ## [v3.0.11] - 2017-06-24
13
+
14
+ - Add shoryuken sqs create command
15
+ - [#388](https://github.com/phstc/shoryuken/pull/388)
16
+
17
+ ## [v3.0.10] - 2017-06-24
18
+
19
+ - Allow aws sdk v3
20
+ - [#381](https://github.com/phstc/shoryuken/pull/381)
21
+
22
+ - Allow configuring Rails via the config file
23
+ - [#387](https://github.com/phstc/shoryuken/pull/387)
24
+
25
+ ## [v3.0.9] - 2017-06-05
26
+
27
+ - Allow configuring queue URLs instead of names
28
+ - [#378](https://github.com/phstc/shoryuken/pull/378)
29
+
30
+ ## [v3.0.8] - 2017-06-02
31
+
32
+ - Fix miss handling empty batch fetches
33
+ - [#376](https://github.com/phstc/shoryuken/pull/376)
34
+
35
+ - Various minor styling changes :lipstick:
36
+ - [#373](https://github.com/phstc/shoryuken/pull/373)
37
+
38
+ - Logout when batch delete returns any failure
39
+ - [#371](https://github.com/phstc/shoryuken/pull/371)
40
+
41
+ ## [v3.0.7] - 2017-05-18
42
+
43
+ - Trigger events for dispatch
44
+ - [#362](https://github.com/phstc/shoryuken/pull/362)
45
+
46
+ - Log (warn) exponential backoff tries
47
+ - [#365](https://github.com/phstc/shoryuken/pull/365)
48
+
49
+ - Fix displaying of long queue names in `shoryuken sqs ls`
50
+ - [#366](https://github.com/phstc/shoryuken/pull/366)
51
+
52
+ ## [v3.0.6] - 2017-04-11
53
+
54
+ - Fix delay option type
55
+ - [#356](https://github.com/phstc/shoryuken/pull/356)
56
+
57
+ ## [v3.0.5] - 2017-04-09
58
+
59
+ - Pause endless dispatcher to avoid CPU overload
60
+ - [#354](https://github.com/phstc/shoryuken/pull/354)
61
+
62
+ - Auto log processor errors
63
+ - [#355](https://github.com/phstc/shoryuken/pull/355)
64
+
65
+ - Add a delay as a CLI param
66
+ - [#350](https://github.com/phstc/shoryuken/pull/350)
67
+
68
+ - Add `sqs purge` command. See https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_PurgeQueue.html
69
+ - [#344](https://github.com/phstc/shoryuken/pull/344)
70
+
1
71
  ## [v3.0.4] - 2017-03-24
72
+
2
73
  - Add `sqs purge` command. See https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_PurgeQueue.html
3
74
  - [#344](https://github.com/phstc/shoryuken/pull/344)
4
75
 
@@ -6,18 +77,22 @@
6
77
  - [#345](https://github.com/phstc/shoryuken/pull/345)
7
78
 
8
79
  ## [v3.0.3] - 2017-03-19
80
+
9
81
  - Update `sqs` CLI commands to use `get_queue_url` when appropriated
10
82
  - [#341](https://github.com/phstc/shoryuken/pull/341)
11
83
 
12
84
  ## [v3.0.2] - 2017-03-19
85
+
13
86
  - Fix custom SQS client initialization
14
87
  - [#335](https://github.com/phstc/shoryuken/pull/335)
15
88
 
16
89
  ## [v3.0.1] - 2017-03-13
90
+
17
91
  - Fix commands sqs mv and dump `options.delete` checker
18
92
  - [#332](https://github.com/phstc/shoryuken/pull/332)
19
93
 
20
94
  ## [v3.0.0] - 2017-03-12
95
+
21
96
  - Replace Celluloid with Concurrent Ruby
22
97
  - [#291](https://github.com/phstc/shoryuken/pull/291)
23
98
 
@@ -37,6 +112,7 @@
37
112
  - [#330](https://github.com/phstc/shoryuken/pull/330)
38
113
 
39
114
  ## [v2.1.3] - 2017-01-27
115
+
40
116
  - Show a warn message when batch isn't supported
41
117
  - [#302](https://github.com/phstc/shoryuken/pull/302)
42
118
 
@@ -47,6 +123,7 @@
47
123
  - [#307](https://github.com/phstc/shoryuken/pull/307)
48
124
 
49
125
  ## [v2.1.2] - 2016-12-22
126
+
50
127
  - Fix loading `logfile` from shoryuken.yml
51
128
  - [#296](https://github.com/phstc/shoryuken/pull/296)
52
129
 
@@ -66,10 +143,12 @@
66
143
  - [#284](https://github.com/phstc/shoryuken/pull/284)
67
144
 
68
145
  ## [v2.1.1] - 2016-12-05
146
+
69
147
  - Fix aws deprecation warning message
70
148
  - [#279](https://github.com/phstc/shoryuken/pull/279)
71
149
 
72
150
  ## [v2.1.0] - 2016-12-03
151
+
73
152
  - Fix celluloid "running in BACKPORTED mode" warning
74
153
  - [#260](https://github.com/phstc/shoryuken/pull/260)
75
154
 
data/Gemfile CHANGED
@@ -7,4 +7,5 @@ group :test do
7
7
  gem 'codeclimate-test-reporter', require: nil
8
8
  gem 'simplecov'
9
9
  gem 'multi_xml'
10
+ gem 'httparty'
10
11
  end
data/README.md CHANGED
@@ -1,42 +1,23 @@
1
1
  # Shoryuken
2
2
 
3
- ![](shoryuken.jpg)
3
+ ![Shoryuken](shoryuken.jpg)
4
4
 
5
- Shoryuken _sho-ryu-ken_ is a super-efficient [AWS SQS](https://aws.amazon.com/sqs/) thread-based message processor.
5
+ Shoryuken _sho-ryu-ken_ is a super-efficient [Amazon SQS](https://aws.amazon.com/sqs/) thread-based message processor.
6
6
 
7
7
  [![Build Status](https://travis-ci.org/phstc/shoryuken.svg)](https://travis-ci.org/phstc/shoryuken)
8
8
  [![Code Climate](https://codeclimate.com/github/phstc/shoryuken/badges/gpa.svg)](https://codeclimate.com/github/phstc/shoryuken)
9
9
 
10
10
  ## Key features
11
11
 
12
- ### Load balancing
13
-
14
- Yeah, Shoryuken load balances the messages consumption!
15
-
16
- Given this configuration:
17
-
18
- ```yaml
19
- concurrency: 25
20
- delay: 25
21
- queues:
22
- - [high_priority, 6]
23
- - [normal_priority, 2]
24
- - [low_priority, 1]
25
- ```
26
-
27
- And supposing all the queues are full of messages, the configuration above will make Shoryuken to process `high_priority` 3 times more than `normal_priority` and 6 times more than `low_priority`,
28
- splitting the work load among all available processors `concurrency: 25` .
29
-
30
- If `high_priority` gets empty, Shoryuken will keep using the 25 processors, but only to process `normal_priority` and `low_priority`.
31
-
32
- If `high_priority` receives a new message, Shoryuken will smoothly increase back its weight one by one until it reaches the weight of 6 again.
33
-
34
- [If a queue gets empty, Shoryuken will pause checking it for `delay: 25`](https://github.com/phstc/shoryuken/wiki/Shoryuken-options#delay).
35
-
36
-
37
- ### Fetch in batches
38
-
39
- To be even more performant and cost effective, Shoryuken fetches SQS messages in batches, so a single SQS request can fetch up to 10 messages.
12
+ - [Rails Active Job](https://github.com/phstc/shoryuken/wiki/Rails-Integration-Active-Job)
13
+ - [Queue Load balancing](https://github.com/phstc/shoryuken/wiki/Shoryuken-options#load-balancing)
14
+ - [Concurrency per queue](https://github.com/phstc/shoryuken/wiki/Processing-Groups)
15
+ - [Long Polling](https://github.com/phstc/shoryuken/wiki/Long-Polling)
16
+ - [Batch processing](https://github.com/phstc/shoryuken/wiki/Worker-options#batch)
17
+ - [Auto extend visibility timeout](https://github.com/phstc/shoryuken/wiki/Worker-options#auto_visibility_timeout)
18
+ - [Exponential backoff](https://github.com/phstc/shoryuken/wiki/Worker-options#retry_intervals)
19
+ - [Middleware support](https://github.com/phstc/shoryuken/wiki/Middleware)
20
+ - Amazon SQS CLI. See `shoryuken help sqs`
40
21
 
41
22
  ## Requirements
42
23
 
@@ -50,102 +31,19 @@ Add this line to your application's Gemfile:
50
31
  gem 'shoryuken'
51
32
  ```
52
33
 
53
- Or to get the latest updates:
54
-
55
- ```ruby
56
- gem 'shoryuken', github: 'phstc/shoryuken', branch: 'master'
57
- ```
58
-
59
34
  And then execute:
60
35
 
61
- $ bundle
62
-
63
- Or install it yourself as:
64
-
65
- $ gem install shoryuken
66
-
67
- ## Usage
68
-
69
- ### Worker class
70
-
71
- ```ruby
72
- class MyWorker
73
- include Shoryuken::Worker
74
-
75
- shoryuken_options queue: 'default', auto_delete: true
76
- # shoryuken_options queue: ->{ "#{ENV['environment']}_default" }
77
-
78
- # shoryuken_options body_parser: :json
79
- # shoryuken_options body_parser: ->(sqs_msg){ REXML::Document.new(sqs_msg.body) }
80
- # shoryuken_options body_parser: JSON
81
-
82
- def perform(sqs_msg, body)
83
- puts body
84
- end
85
- end
86
- ```
87
-
88
- [Check the Worker options documention](https://github.com/phstc/shoryuken/wiki/Worker-options).
89
-
90
- ### Sending a message
91
-
92
- [Check the Sending a message documentation](https://github.com/phstc/shoryuken/wiki/Sending-a-message)
93
-
94
- ### Middleware
95
-
96
- ```ruby
97
- class MyMiddleware
98
- def call(worker_instance, queue, sqs_msg, body)
99
- puts 'Before work'
100
- yield
101
- puts 'After work'
102
- end
103
- end
104
- ```
105
-
106
- [Check the Middleware documentation](https://github.com/phstc/shoryuken/wiki/Middleware).
107
-
108
- ### Shoryuken Configuration
109
-
110
- Sample configuration file `shoryuken.yml`.
111
-
112
- ```yaml
113
- concurrency: 25 # The number of allocated threads to process messages. Default 25
114
- delay: 25 # The delay in seconds to pause a queue when it's empty. Default 0
115
- queues:
116
- - [high_priority, 6]
117
- - [normal_priority, 2]
118
- - [low_priority, 1]
119
- ```
120
-
121
- #### AWS Configuration
122
-
123
- [Check the Configure AWS Client documentation](https://github.com/phstc/shoryuken/wiki/Configure-the-AWS-Client)
124
-
125
- ### Rails Integration
126
-
127
- [Check the Rails Integration Active Job documention](https://github.com/phstc/shoryuken/wiki/Rails-Integration-Active-Job).
128
-
129
- ### Start Shoryuken
130
-
131
36
  ```shell
132
- bundle exec shoryuken -r worker.rb -C shoryuken.yml
37
+ $ bundle
133
38
  ```
134
39
 
135
- For other options check `bundle exec shoryuken help start`
136
-
137
- #### SQS commands
138
-
139
- Check also some available SQS commands `bundle exec shoryuken help sqs`, such as:
40
+ ## Usage
140
41
 
141
- - `ls` list queues
142
- - `mv` move messages from one queue to another
143
- - `dump` dump messages from a queue into a JSON lines file
144
- - `requeue` requeue messages from a dump file
42
+ Check the [Getting Started](https://github.com/phstc/shoryuken/wiki/Getting-Started) page.
145
43
 
146
44
  ## More Information
147
45
 
148
- For more information on advanced topics such as signals (shutdown), ActiveJob integration, and so on please check the [Shoryuken Wiki](https://github.com/phstc/shoryuken/wiki).
46
+ For more information check the [wiki page](https://github.com/phstc/shoryuken/wiki).
149
47
 
150
48
  ## Credits
151
49
 
data/bin/cli/base.rb CHANGED
@@ -25,10 +25,8 @@ module Shoryuken
25
25
  end
26
26
 
27
27
  def print_format_column(column, size)
28
- size = 40 if size > 40
29
28
  size_with_padding = size + 4
30
29
  column = column.to_s.ljust(size_with_padding)
31
- column = "#{column[0...size - 2]}.." if column.size > size_with_padding
32
30
  column
33
31
  end
34
32
 
data/bin/cli/sqs.rb CHANGED
@@ -32,7 +32,10 @@ module Shoryuken
32
32
  queue_url: url,
33
33
  entries: batch.map { |message| { id: message.message_id, receipt_handle: message.receipt_handle } }
34
34
  ).failed.any? do |failure|
35
- say "Could not delete #{failure.id}, code: #{failure.code}", :yellow
35
+ say(
36
+ "Could not delete #{failure.id}, code: #{failure.code}, message: #{failure.message}, sender_fault: #{failure.sender_fault}",
37
+ :yellow
38
+ )
36
39
  end
37
40
  end
38
41
  end
@@ -182,6 +185,20 @@ module Shoryuken
182
185
 
183
186
  say "Purge request sent for #{queue_name}. The message deletion process takes up to 60 seconds", :yellow
184
187
  end
188
+
189
+ desc 'create QUEUE-NAME', 'Create a queue'
190
+ def create(queue_name)
191
+ queue_url = sqs.create_queue(queue_name: queue_name).queue_url
192
+
193
+ say "Queue #{queue_name} was successfully created. Queue URL #{queue_url}", :green
194
+ end
195
+
196
+ desc 'delete QUEUE-NAME', 'delete a queue'
197
+ def delete(queue_name)
198
+ sqs.delete_queue(queue_url: find_queue_url(queue_name))
199
+
200
+ say "Queue #{queue_name} was successfully delete", :green
201
+ end
185
202
  end
186
203
  end
187
204
  end
data/bin/shoryuken CHANGED
@@ -21,14 +21,22 @@ module Shoryuken
21
21
  method_option :daemon, aliases: '-d', type: :boolean, desc: 'Daemonize process'
22
22
  method_option :queues, aliases: '-q', type: :array, desc: 'Queues to process with optional weights'
23
23
  method_option :require, aliases: '-r', type: :string, desc: 'Dir or path of the workers'
24
- method_option :config_file, aliases: '-C', type: :string, desc: 'Path to config file'
24
+ method_option :config, aliases: '-C', type: :string, desc: 'Path to config file'
25
+ method_option :config_file, type: :string, desc: 'Path to config file (backwards compatibility)'
25
26
  method_option :rails, aliases: '-R', type: :boolean, desc: 'Load Rails'
26
27
  method_option :logfile, aliases: '-L', type: :string, desc: 'Path to logfile'
27
28
  method_option :pidfile, aliases: '-P', type: :string, desc: 'Path to pidfile'
28
29
  method_option :verbose, aliases: '-v', type: :boolean, desc: 'Print more verbose output'
30
+ method_option :delay, aliases: '-D', type: :numeric, desc: 'Number of seconds to pause fetching from an empty queue'
29
31
  def start
30
32
  opts = options.to_h.symbolize_keys
31
33
 
34
+ if opts[:config_file]
35
+ say "[DEPRECATED] Please use --config instead of --config-file", :yellow
36
+ end
37
+
38
+ opts[:config_file] = opts.delete(:config) if opts[:config]
39
+
32
40
  # Keep compatibility with old CLI queue format
33
41
  opts[:queues] = options[:queues].map { |q| q.split(',') } if options[:queues]
34
42
 
@@ -4,6 +4,6 @@ class DefaultWorker
4
4
  shoryuken_options queue: 'default', auto_delete: true
5
5
 
6
6
  def perform(sqs_msg, body)
7
- Shoryuken.logger.debug("Received message: '#{body}'")
7
+ Shoryuken.logger.debug("Received message: #{body}")
8
8
  end
9
9
  end
@@ -24,7 +24,7 @@ module Shoryuken
24
24
  @workers[queue]
25
25
  end
26
26
 
27
- worker_class.new
27
+ worker_class.new if worker_class
28
28
  end
29
29
 
30
30
  def queues
@@ -34,7 +34,7 @@ module Shoryuken
34
34
  def register_worker(queue, clazz)
35
35
  if (worker_class = @workers[queue])
36
36
  if worker_class.get_shoryuken_options['batch'] == true || clazz.get_shoryuken_options['batch'] == true
37
- fail ArgumentError, "Could not register #{clazz} for '#{queue}', "\
37
+ fail ArgumentError, "Could not register #{clazz} for #{queue}, "\
38
38
  "because #{worker_class} is already registered for this queue, "\
39
39
  "and Shoryuken doesn't support a batchable worker for a queue with multiple workers"
40
40
  end
@@ -24,7 +24,7 @@ module Shoryuken
24
24
  end
25
25
 
26
26
  def load
27
- load_rails if options[:rails]
27
+ load_rails if Shoryuken.options[:rails]
28
28
  prefix_active_job_queue_names
29
29
  parse_queues
30
30
  require_workers
@@ -42,9 +42,13 @@ module Shoryuken
42
42
  def config_file_options
43
43
  return {} unless (path = options[:config_file])
44
44
 
45
- fail ArgumentError, "The supplied config file '#{path}' does not exist" unless File.exist?(path)
45
+ fail ArgumentError, "The supplied config file #{path} does not exist" unless File.exist?(path)
46
46
 
47
- YAML.load(ERB.new(IO.read(path)).result).deep_symbolize_keys
47
+ if result = YAML.load(ERB.new(IO.read(path)).result)
48
+ result.deep_symbolize_keys
49
+ else
50
+ {}
51
+ end
48
52
  end
49
53
 
50
54
  def initialize_logger
@@ -96,13 +100,24 @@ module Shoryuken
96
100
  end
97
101
  end
98
102
 
99
- def parse_queue(queue, weight = nil)
100
- Shoryuken.add_queue(queue, [weight.to_i, 1].max)
103
+ def parse_queue(queue, weight = nil, group)
104
+ Shoryuken.add_queue(queue, [weight.to_i, 1].max, group)
101
105
  end
102
106
 
103
107
  def parse_queues
104
- Shoryuken.options[:queues].to_a.each do |queue_and_weight|
105
- parse_queue(*queue_and_weight)
108
+ if Shoryuken.options[:queues].to_a.any?
109
+ Shoryuken.add_group('default', Shoryuken.options.fetch(:concurrency, 25))
110
+
111
+ Shoryuken.options[:queues].to_a.each do |queue, weight|
112
+ parse_queue(queue, weight, 'default')
113
+ end
114
+ end
115
+
116
+ Shoryuken.options[:groups].to_a.each do |group, options|
117
+ Shoryuken.add_group(group, options.fetch(:concurrency, 25))
118
+ options[:queues].to_a.each do |queue, weight|
119
+ parse_queue(queue, weight, group)
120
+ end
106
121
  end
107
122
  end
108
123
 
@@ -119,29 +134,34 @@ module Shoryuken
119
134
  end
120
135
 
121
136
  def validate_queues
122
- Shoryuken.logger.warn { 'No queues supplied' } if Shoryuken.queues.empty?
137
+ return Shoryuken.logger.warn { 'No queues supplied' } if Shoryuken.ungrouped_queues.empty?
123
138
 
124
139
  non_existent_queues = []
125
140
 
126
- Shoryuken.queues.uniq.each do |queue|
141
+ Shoryuken.ungrouped_queues.uniq.each do |queue|
127
142
  begin
128
143
  Shoryuken::Client.queues(queue)
129
- rescue Aws::SQS::Errors::NonExistentQueue
144
+ rescue Aws::Errors::NoSuchEndpointError, Aws::SQS::Errors::NonExistentQueue
130
145
  non_existent_queues << queue
131
146
  end
132
147
  end
133
148
 
134
- fail ArgumentError, "The specified queue(s) #{non_existent_queues} do not exist" if non_existent_queues.any?
149
+ return if non_existent_queues.none?
150
+
151
+ fail(
152
+ ArgumentError,
153
+ "The specified queue(s) #{non_existent_queues.join(', ')} do not exist.\nTry 'shoryuken sqs create QUEUE-NAME' for creating a queue with default settings"
154
+ )
135
155
  end
136
156
 
137
157
  def validate_workers
138
158
  return if defined?(::ActiveJob)
139
159
 
140
- all_queues = Shoryuken.queues
160
+ all_queues = Shoryuken.ungrouped_queues
141
161
  queues_with_workers = Shoryuken.worker_registry.queues
142
162
 
143
163
  (all_queues - queues_with_workers).each do |queue|
144
- Shoryuken.logger.warn { "No worker supplied for '#{queue}'" }
164
+ Shoryuken.logger.warn { "No worker supplied for #{queue}" }
145
165
  end
146
166
  end
147
167
  end
@@ -4,23 +4,23 @@ module Shoryuken
4
4
 
5
5
  FETCH_LIMIT = 10
6
6
 
7
- def fetch(queue, available_processors)
7
+ attr_reader :group
8
+
9
+ def initialize(group)
10
+ @group = group
11
+ end
12
+
13
+ def fetch(queue, limit)
8
14
  started_at = Time.now
9
15
 
10
- logger.debug { "Looking for new messages in '#{queue}'" }
16
+ logger.debug { "Looking for new messages in #{queue}" }
11
17
 
12
- begin
13
- limit = available_processors > FETCH_LIMIT ? FETCH_LIMIT : available_processors
18
+ sqs_msgs = Array(receive_messages(queue, [FETCH_LIMIT, limit].min))
14
19
 
15
- sqs_msgs = Array(receive_messages(queue, limit))
16
- logger.info { "Found #{sqs_msgs.size} messages for '#{queue.name}'" } unless sqs_msgs.empty?
17
- logger.debug { "Fetcher for '#{queue}' completed in #{elapsed(started_at)} ms" }
18
- sqs_msgs
19
- rescue => ex
20
- logger.error { "Error fetching message: #{ex}" }
21
- logger.error { ex.backtrace.first }
22
- []
23
- end
20
+ logger.info { "Found #{sqs_msgs.size} messages for #{queue.name}" } unless sqs_msgs.empty?
21
+ logger.debug { "Fetcher for #{queue} completed in #{elapsed(started_at)} ms" }
22
+
23
+ sqs_msgs
24
24
  end
25
25
 
26
26
  private
@@ -29,10 +29,11 @@ module Shoryuken
29
29
  # AWS limits the batch size by 10
30
30
  limit = limit > FETCH_LIMIT ? FETCH_LIMIT : limit
31
31
 
32
- options = Shoryuken.sqs_client_receive_message_opts.to_h.dup
33
- options[:max_number_of_messages] = limit
32
+ options = Shoryuken.sqs_client_receive_message_opts[group].to_h.dup
33
+
34
+ options[:max_number_of_messages] = limit
34
35
  options[:message_attribute_names] = %w(All)
35
- options[:attribute_names] = %w(All)
36
+ options[:attribute_names] = %w(All)
36
37
 
37
38
  options.merge!(queue.options)
38
39
 
@@ -3,17 +3,96 @@ module Shoryuken
3
3
  include Util
4
4
 
5
5
  def initialize
6
- @manager = Shoryuken::Manager.new(Shoryuken::Fetcher.new,
7
- Shoryuken.options[:polling_strategy].new(Shoryuken.queues))
6
+ @managers = create_managers
7
+ @shutdowning = Concurrent::AtomicBoolean.new(false)
8
8
  end
9
9
 
10
- def stop(options = {})
11
- @manager.stop(shutdown: !options[:shutdown].nil?,
12
- timeout: Shoryuken.options[:timeout])
10
+ def start
11
+ logger.info { 'Starting' }
12
+
13
+ start_callback
14
+ start_managers
15
+ end
16
+
17
+ def stop!
18
+ initiate_stop
19
+
20
+ executor.shutdown
21
+
22
+ return if executor.wait_for_termination(Shoryuken.options[:timeout])
23
+
24
+ executor.kill
25
+ end
26
+
27
+ def stop
28
+ fire_event(:quiet, true)
29
+
30
+ initiate_stop
31
+
32
+ executor.shutdown
33
+ executor.wait_for_termination
34
+ end
35
+
36
+ private
37
+
38
+ def executor
39
+ Concurrent.global_io_executor
40
+ end
41
+
42
+ def start_managers
43
+ @managers.each do |manager|
44
+ Concurrent::Promise.execute { manager.start }.rescue do |ex|
45
+ log_manager_failure(ex)
46
+ start_soft_shutdown
47
+ end
48
+ end
49
+ end
50
+
51
+ def start_soft_shutdown
52
+ Process.kill('USR1', Process.pid) if @shutdowning.make_true
53
+ end
54
+
55
+ def log_manager_failure(ex)
56
+ return unless ex
57
+
58
+ logger.error { "Manager failed: #{ex.message}" }
59
+ logger.error { ex.backtrace.join("\n") } unless ex.backtrace.nil?
60
+ end
61
+
62
+ def initiate_stop
63
+ logger.info { 'Shutting down' }
64
+
65
+ @managers.each(&:stop)
66
+
67
+ stop_callback
68
+ end
69
+
70
+ def start_callback
71
+ if (callback = Shoryuken.start_callback)
72
+ logger.debug { 'Calling start_callback' }
73
+ callback.call
74
+ end
75
+
76
+ fire_event(:startup)
77
+ end
78
+
79
+ def stop_callback
80
+ if (callback = Shoryuken.stop_callback)
81
+ logger.debug { 'Calling stop_callback' }
82
+ callback.call
83
+ end
84
+
85
+ fire_event(:shutdown, true)
13
86
  end
14
87
 
15
- def run
16
- @manager.start
88
+ def create_managers
89
+ Shoryuken.groups.map do |group, options|
90
+ Shoryuken::Manager.new(
91
+ Shoryuken::Fetcher.new(group),
92
+ Shoryuken.polling_strategy(group).new(options[:queues]),
93
+ options[:concurrency]
94
+ )
95
+ end
17
96
  end
18
97
  end
19
98
  end