shoryuken 3.1.0 → 3.2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +13 -3
- data/CHANGELOG.md +89 -0
- data/Gemfile +5 -2
- data/Gemfile.aws-sdk-core-v2 +13 -0
- data/bin/cli/sqs.rb +8 -4
- data/bin/shoryuken +2 -1
- data/lib/shoryuken/body_parser.rb +27 -0
- data/lib/shoryuken/environment_loader.rb +25 -11
- data/lib/shoryuken/fetcher.rb +40 -13
- data/lib/shoryuken/launcher.rb +4 -20
- data/lib/shoryuken/logging.rb +0 -5
- data/lib/shoryuken/manager.rb +33 -24
- data/lib/shoryuken/middleware/chain.rb +4 -0
- data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +2 -5
- data/lib/shoryuken/middleware/server/timing.rb +12 -14
- data/lib/shoryuken/options.rb +25 -1
- data/lib/shoryuken/processor.rb +9 -21
- data/lib/shoryuken/queue.rb +12 -5
- data/lib/shoryuken/runner.rb +3 -1
- data/lib/shoryuken/util.rb +3 -3
- data/lib/shoryuken/version.rb +1 -1
- data/lib/shoryuken/worker/default_executor.rb +33 -0
- data/lib/shoryuken/worker/inline_executor.rb +28 -0
- data/lib/shoryuken/worker.rb +68 -31
- data/lib/shoryuken.rb +14 -1
- data/shoryuken.gemspec +1 -1
- data/spec/shoryuken/body_parser_spec.rb +89 -0
- data/spec/shoryuken/environment_loader_spec.rb +32 -3
- data/spec/shoryuken/fetcher_spec.rb +61 -9
- data/spec/shoryuken/manager_spec.rb +49 -20
- data/spec/shoryuken/middleware/chain_spec.rb +16 -4
- data/spec/shoryuken/middleware/server/timing_spec.rb +5 -3
- data/spec/shoryuken/options_spec.rb +80 -0
- data/spec/shoryuken/processor_spec.rb +15 -97
- data/spec/shoryuken/queue_spec.rb +43 -32
- data/spec/shoryuken/util_spec.rb +25 -1
- data/spec/shoryuken/worker/default_executor_spec.rb +100 -0
- data/spec/shoryuken/worker/inline_executor_spec.rb +23 -0
- data/spec/shoryuken/worker_spec.rb +32 -91
- data/spec/spec_helper.rb +5 -0
- metadata +15 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f74e5fbb599fe5bbe41bed5fd542c0c1fdcc2d35
|
|
4
|
+
data.tar.gz: 6099d42682b5e2a1797d7cdbdc7bf27b344b692c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f076e8f427f39ca92be4f27be819350d90270ce9e695d1173a6944b82d16680d11afd78a0075dd549e0a2c6031e6d5708c306cb245c4d7dfcc69d8a5e7151bc7
|
|
7
|
+
data.tar.gz: 2fd34c84e6260df3c35427ffb27d3d067fc1ea11469609d61e8eedd465e4516d75e052079b5195ede7c7917ad3c97bb39c5440bc5436ae3ab2581f3fb72bad31
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
language: ruby
|
|
2
|
+
|
|
2
3
|
rvm:
|
|
3
4
|
- 2.0.0
|
|
4
|
-
- 2.1.
|
|
5
|
+
- 2.1.10
|
|
5
6
|
- 2.2.0
|
|
6
7
|
- 2.3.3
|
|
7
8
|
- 2.4.1
|
|
@@ -11,9 +12,18 @@ notifications:
|
|
|
11
12
|
on_success: change
|
|
12
13
|
on_failure: always
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
gemfile:
|
|
16
|
+
- Gemfile
|
|
17
|
+
- Gemfile.aws-sdk-core-v2
|
|
18
|
+
|
|
19
|
+
env:
|
|
20
|
+
- SPEC_ALL=true
|
|
21
|
+
|
|
22
|
+
script: bundle exec rspec spec
|
|
23
|
+
|
|
15
24
|
before_install:
|
|
16
|
-
|
|
25
|
+
- gem update bundler
|
|
26
|
+
|
|
17
27
|
after_success:
|
|
18
28
|
- bundle exec codeclimate-test-reporter
|
|
19
29
|
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,92 @@
|
|
|
1
|
+
## [v3.2.0] - 2018-01-03
|
|
2
|
+
|
|
3
|
+
- Preserve parent worker class options
|
|
4
|
+
- [#451](https://github.com/phstc/shoryuken/pull/451)
|
|
5
|
+
|
|
6
|
+
- Add -t (shutdown timeout) option to CL
|
|
7
|
+
- [#449](https://github.com/phstc/shoryuken/pull/449)
|
|
8
|
+
|
|
9
|
+
- Support inline (Active Job like) for standard workers
|
|
10
|
+
- [#448](https://github.com/phstc/shoryuken/pull/448)
|
|
11
|
+
|
|
12
|
+
## [v3.1.12] - 2017-09-25
|
|
13
|
+
|
|
14
|
+
- Reduce fetch log verbosity
|
|
15
|
+
- [#436](https://github.com/phstc/shoryuken/pull/436)
|
|
16
|
+
|
|
17
|
+
## [v3.1.11] - 2017-09-02
|
|
18
|
+
|
|
19
|
+
- Auto retry (up to 3 times) fetch errors
|
|
20
|
+
- [#429](https://github.com/phstc/shoryuken/pull/429)
|
|
21
|
+
|
|
22
|
+
## [v3.1.10] - 2017-09-02
|
|
23
|
+
|
|
24
|
+
- Make Shoryuken compatible with AWS SDK 3 and 2
|
|
25
|
+
- [#433](https://github.com/phstc/shoryuken/pull/433)
|
|
26
|
+
|
|
27
|
+
## [v3.1.9] - 2017-08-24
|
|
28
|
+
|
|
29
|
+
- Add support for adding a middleware to the front of chain
|
|
30
|
+
- [#427](https://github.com/phstc/shoryuken/pull/427)
|
|
31
|
+
|
|
32
|
+
- Add support for dispatch fire event
|
|
33
|
+
- [#426](https://github.com/phstc/shoryuken/pull/426)
|
|
34
|
+
|
|
35
|
+
## [v3.1.8] - 2017-08-17
|
|
36
|
+
|
|
37
|
+
- Make Polling strategy backward compatibility
|
|
38
|
+
- [#424](https://github.com/phstc/shoryuken/pull/424)
|
|
39
|
+
|
|
40
|
+
## [v3.1.7] - 2017-07-31
|
|
41
|
+
|
|
42
|
+
- Allow polling strategy per group
|
|
43
|
+
- [#417](https://github.com/phstc/shoryuken/pull/417)
|
|
44
|
+
|
|
45
|
+
- Add support for creating FIFO queues
|
|
46
|
+
- [#419](https://github.com/phstc/shoryuken/pull/419)
|
|
47
|
+
|
|
48
|
+
- Allow receive message options per queue
|
|
49
|
+
- [#420](https://github.com/phstc/shoryuken/pull/420)
|
|
50
|
+
|
|
51
|
+
## [v3.1.6] - 2017-07-24
|
|
52
|
+
|
|
53
|
+
- Fix issue with dispatch_loop and delays
|
|
54
|
+
- [#416](https://github.com/phstc/shoryuken/pull/416)
|
|
55
|
+
|
|
56
|
+
## [v3.1.5] - 2017-07-23
|
|
57
|
+
|
|
58
|
+
- Fix memory leak
|
|
59
|
+
- [#414](https://github.com/phstc/shoryuken/pull/414)
|
|
60
|
+
|
|
61
|
+
- Fail fast on bad queue URLs
|
|
62
|
+
- [#413](https://github.com/phstc/shoryuken/pull/413)
|
|
63
|
+
|
|
64
|
+
## [v3.1.4] - 2017-07-14
|
|
65
|
+
|
|
66
|
+
- Require forwardable allowding to call `shoryuken` without `bundle exec`
|
|
67
|
+
- [#409](https://github.com/phstc/shoryuken/pull/409)
|
|
68
|
+
|
|
69
|
+
## [v3.1.3] - 2017-07-11
|
|
70
|
+
|
|
71
|
+
- Add queue prefixing support for groups
|
|
72
|
+
- [#405](https://github.com/phstc/shoryuken/pull/405)
|
|
73
|
+
|
|
74
|
+
- Remove dead code
|
|
75
|
+
- [#402](https://github.com/phstc/shoryuken/pull/402)
|
|
76
|
+
|
|
77
|
+
## [v3.1.2] - 2017-07-06
|
|
78
|
+
|
|
79
|
+
- Fix stack level too deep on Ubuntu
|
|
80
|
+
- [#400](https://github.com/phstc/shoryuken/pull/400)
|
|
81
|
+
|
|
82
|
+
## [v3.1.1] - 2017-07-05
|
|
83
|
+
|
|
84
|
+
- Reduce log verbosity introduced in 3.1.0
|
|
85
|
+
- [#397](https://github.com/phstc/shoryuken/pull/397)
|
|
86
|
+
|
|
87
|
+
- Try to prevent stack level too deep on Ubuntu
|
|
88
|
+
- [#396](https://github.com/phstc/shoryuken/pull/396)
|
|
89
|
+
|
|
1
90
|
## [v3.1.0] - 2017-07-02
|
|
2
91
|
|
|
3
92
|
- Add shoryuken sqs delete command
|
data/Gemfile
CHANGED
|
@@ -4,8 +4,11 @@ source 'https://rubygems.org'
|
|
|
4
4
|
gemspec
|
|
5
5
|
|
|
6
6
|
group :test do
|
|
7
|
+
gem 'activejob', '~> 4'
|
|
8
|
+
gem 'aws-sdk-core', '~> 3'
|
|
9
|
+
gem 'aws-sdk-sqs'
|
|
7
10
|
gem 'codeclimate-test-reporter', require: nil
|
|
8
|
-
gem 'simplecov'
|
|
9
|
-
gem 'multi_xml'
|
|
10
11
|
gem 'httparty'
|
|
12
|
+
gem 'multi_xml'
|
|
13
|
+
gem 'simplecov'
|
|
11
14
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
source 'https://rubygems.org'
|
|
2
|
+
|
|
3
|
+
# Specify your gem's dependencies in shoryuken.gemspec
|
|
4
|
+
gemspec
|
|
5
|
+
|
|
6
|
+
group :test do
|
|
7
|
+
gem 'activejob', '~> 4'
|
|
8
|
+
gem 'aws-sdk-core', '~> 2'
|
|
9
|
+
gem 'codeclimate-test-reporter', require: nil
|
|
10
|
+
gem 'httparty'
|
|
11
|
+
gem 'multi_xml'
|
|
12
|
+
gem 'simplecov'
|
|
13
|
+
end
|
data/bin/cli/sqs.rb
CHANGED
|
@@ -96,8 +96,8 @@ module Shoryuken
|
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
desc 'ls [QUEUE-NAME-PREFIX]', 'Lists queues'
|
|
99
|
-
method_option :watch,
|
|
100
|
-
method_option :
|
|
99
|
+
method_option :watch, aliases: '-w', type: :boolean, desc: 'watch queues'
|
|
100
|
+
method_option :interval, aliases: '-n', type: :numeric, default: 2, desc: 'watch interval in seconds'
|
|
101
101
|
def ls(queue_name_prefix = '')
|
|
102
102
|
trap('SIGINT', 'EXIT') # expect ctrl-c from loop
|
|
103
103
|
|
|
@@ -108,7 +108,7 @@ module Shoryuken
|
|
|
108
108
|
|
|
109
109
|
break unless options[:watch]
|
|
110
110
|
|
|
111
|
-
sleep options[:
|
|
111
|
+
sleep options[:interval]
|
|
112
112
|
puts
|
|
113
113
|
end
|
|
114
114
|
end
|
|
@@ -187,8 +187,12 @@ module Shoryuken
|
|
|
187
187
|
end
|
|
188
188
|
|
|
189
189
|
desc 'create QUEUE-NAME', 'Create a queue'
|
|
190
|
+
method_option :attributes, aliases: '-a', type: :hash, default: {}, desc: 'queue attributes'
|
|
190
191
|
def create(queue_name)
|
|
191
|
-
|
|
192
|
+
attributes = options[:attributes]
|
|
193
|
+
attributes['FifoQueue'] ||= 'true' if queue_name.end_with?('.fifo')
|
|
194
|
+
|
|
195
|
+
queue_url = sqs.create_queue(queue_name: queue_name, attributes: attributes).queue_url
|
|
192
196
|
|
|
193
197
|
say "Queue #{queue_name} was successfully created. Queue URL #{queue_url}", :green
|
|
194
198
|
end
|
data/bin/shoryuken
CHANGED
|
@@ -21,6 +21,7 @@ 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 :timeout, aliases: '-t', type: :numeric, desc: 'Hard shutdown timeout'
|
|
24
25
|
method_option :config, aliases: '-C', type: :string, desc: 'Path to config file'
|
|
25
26
|
method_option :config_file, type: :string, desc: 'Path to config file (backwards compatibility)'
|
|
26
27
|
method_option :rails, aliases: '-R', type: :boolean, desc: 'Load Rails'
|
|
@@ -32,7 +33,7 @@ module Shoryuken
|
|
|
32
33
|
opts = options.to_h.symbolize_keys
|
|
33
34
|
|
|
34
35
|
if opts[:config_file]
|
|
35
|
-
say
|
|
36
|
+
say '[DEPRECATED] Please use --config instead of --config-file', :yellow
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
opts[:config_file] = opts.delete(:config) if opts[:config]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Shoryuken
|
|
2
|
+
class BodyParser
|
|
3
|
+
class << self
|
|
4
|
+
def parse(worker_class, sqs_msg)
|
|
5
|
+
body_parser = worker_class.get_shoryuken_options['body_parser']
|
|
6
|
+
|
|
7
|
+
case body_parser
|
|
8
|
+
when :json
|
|
9
|
+
JSON.parse(sqs_msg.body)
|
|
10
|
+
when Proc
|
|
11
|
+
body_parser.call(sqs_msg)
|
|
12
|
+
when :text, nil
|
|
13
|
+
sqs_msg.body
|
|
14
|
+
else
|
|
15
|
+
if body_parser.respond_to?(:parse)
|
|
16
|
+
# JSON.parse
|
|
17
|
+
body_parser.parse(sqs_msg.body)
|
|
18
|
+
elsif body_parser.respond_to?(:load)
|
|
19
|
+
# see https://github.com/phstc/shoryuken/pull/91
|
|
20
|
+
# JSON.load
|
|
21
|
+
body_parser.load(sqs_msg.body)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -44,7 +44,7 @@ module Shoryuken
|
|
|
44
44
|
|
|
45
45
|
fail ArgumentError, "The supplied config file #{path} does not exist" unless File.exist?(path)
|
|
46
46
|
|
|
47
|
-
if result = YAML.load(ERB.new(IO.read(path)).result)
|
|
47
|
+
if (result = YAML.load(ERB.new(IO.read(path)).result))
|
|
48
48
|
result.deep_symbolize_keys
|
|
49
49
|
else
|
|
50
50
|
{}
|
|
@@ -69,7 +69,7 @@ module Shoryuken
|
|
|
69
69
|
::Rails::Application.initializer 'shoryuken.eager_load' do
|
|
70
70
|
::Rails.application.config.eager_load = true
|
|
71
71
|
end
|
|
72
|
-
require 'shoryuken/extensions/active_job_adapter' if
|
|
72
|
+
require 'shoryuken/extensions/active_job_adapter' if Shoryuken.active_job?
|
|
73
73
|
require File.expand_path('config/environment.rb')
|
|
74
74
|
end
|
|
75
75
|
end
|
|
@@ -85,22 +85,36 @@ module Shoryuken
|
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
-
def
|
|
89
|
-
return unless defined? ::ActiveJob
|
|
90
|
-
return unless Shoryuken.active_job_queue_name_prefixing
|
|
91
|
-
|
|
88
|
+
def prefix_active_job_queue_name(queue_name, weight)
|
|
92
89
|
queue_name_prefix = ::ActiveJob::Base.queue_name_prefix
|
|
93
90
|
queue_name_delimiter = ::ActiveJob::Base.queue_name_delimiter
|
|
94
91
|
|
|
95
92
|
# See https://github.com/rails/rails/blob/master/activejob/lib/active_job/queue_name.rb#L27
|
|
93
|
+
name_parts = [queue_name_prefix.presence, queue_name]
|
|
94
|
+
prefixed_queue_name = name_parts.compact.join(queue_name_delimiter)
|
|
95
|
+
[prefixed_queue_name, weight]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def prefix_active_job_queue_names
|
|
99
|
+
return unless Shoryuken.active_job?
|
|
100
|
+
return unless Shoryuken.active_job_queue_name_prefixing
|
|
101
|
+
|
|
96
102
|
Shoryuken.options[:queues].to_a.map! do |queue_name, weight|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
prefix_active_job_queue_name(queue_name, weight)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
Shoryuken.options[:groups].to_a.map! do |group, options|
|
|
107
|
+
if options[:queues]
|
|
108
|
+
options[:queues].map! do |queue_name, weight|
|
|
109
|
+
prefix_active_job_queue_name(queue_name, weight)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
[group, options]
|
|
100
114
|
end
|
|
101
115
|
end
|
|
102
116
|
|
|
103
|
-
def parse_queue(queue, weight
|
|
117
|
+
def parse_queue(queue, weight, group)
|
|
104
118
|
Shoryuken.add_queue(queue, [weight.to_i, 1].max, group)
|
|
105
119
|
end
|
|
106
120
|
|
|
@@ -155,7 +169,7 @@ module Shoryuken
|
|
|
155
169
|
end
|
|
156
170
|
|
|
157
171
|
def validate_workers
|
|
158
|
-
return if
|
|
172
|
+
return if Shoryuken.active_job?
|
|
159
173
|
|
|
160
174
|
all_queues = Shoryuken.ungrouped_queues
|
|
161
175
|
queues_with_workers = Shoryuken.worker_registry.queues
|
data/lib/shoryuken/fetcher.rb
CHANGED
|
@@ -4,34 +4,50 @@ module Shoryuken
|
|
|
4
4
|
|
|
5
5
|
FETCH_LIMIT = 10
|
|
6
6
|
|
|
7
|
-
attr_reader :group
|
|
8
|
-
|
|
9
7
|
def initialize(group)
|
|
10
8
|
@group = group
|
|
11
9
|
end
|
|
12
10
|
|
|
13
11
|
def fetch(queue, limit)
|
|
14
|
-
|
|
12
|
+
fetch_with_auto_retry(3) do
|
|
13
|
+
started_at = Time.now
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
logger.debug { "Looking for new messages in #{queue}" }
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
sqs_msgs = Array(receive_messages(queue, [FETCH_LIMIT, limit].min))
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
logger.debug { "Found #{sqs_msgs.size} messages for #{queue.name}" } unless sqs_msgs.empty?
|
|
20
|
+
logger.debug { "Fetcher for #{queue} completed in #{elapsed(started_at)} ms" }
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
sqs_msgs
|
|
23
|
+
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
private
|
|
27
27
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
def fetch_with_auto_retry(max_attempts, &block)
|
|
29
|
+
attempts = 0
|
|
30
|
+
|
|
31
|
+
begin
|
|
32
|
+
yield
|
|
33
|
+
rescue => ex
|
|
34
|
+
# Tries to auto retry connectivity errors
|
|
35
|
+
raise if attempts >= max_attempts
|
|
36
|
+
|
|
37
|
+
attempts += 1
|
|
38
|
+
|
|
39
|
+
logger.debug { "Retrying fetch attempt #{attempts} for #{ex.message}" }
|
|
40
|
+
|
|
41
|
+
sleep((1..5).to_a.sample)
|
|
42
|
+
|
|
43
|
+
retry
|
|
44
|
+
end
|
|
45
|
+
end
|
|
31
46
|
|
|
32
|
-
|
|
47
|
+
def receive_messages(queue, limit)
|
|
48
|
+
options = receive_options(queue)
|
|
33
49
|
|
|
34
|
-
options[:max_number_of_messages] = limit
|
|
50
|
+
options[:max_number_of_messages] = max_number_of_messages(limit, options)
|
|
35
51
|
options[:message_attribute_names] = %w(All)
|
|
36
52
|
options[:attribute_names] = %w(All)
|
|
37
53
|
|
|
@@ -39,5 +55,16 @@ module Shoryuken
|
|
|
39
55
|
|
|
40
56
|
Shoryuken::Client.queues(queue.name).receive_messages(options)
|
|
41
57
|
end
|
|
58
|
+
|
|
59
|
+
def max_number_of_messages(limit, options)
|
|
60
|
+
[limit, FETCH_LIMIT, options[:max_number_of_messages]].compact.min
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def receive_options(queue)
|
|
64
|
+
options = Shoryuken.sqs_client_receive_message_opts[queue.name]
|
|
65
|
+
options ||= Shoryuken.sqs_client_receive_message_opts[@group]
|
|
66
|
+
|
|
67
|
+
options.to_h.dup
|
|
68
|
+
end
|
|
42
69
|
end
|
|
43
70
|
end
|
data/lib/shoryuken/launcher.rb
CHANGED
|
@@ -3,8 +3,7 @@ module Shoryuken
|
|
|
3
3
|
include Util
|
|
4
4
|
|
|
5
5
|
def initialize
|
|
6
|
-
@managers
|
|
7
|
-
@shutdowning = Concurrent::AtomicBoolean.new(false)
|
|
6
|
+
@managers = create_managers
|
|
8
7
|
end
|
|
9
8
|
|
|
10
9
|
def start
|
|
@@ -41,29 +40,13 @@ module Shoryuken
|
|
|
41
40
|
|
|
42
41
|
def start_managers
|
|
43
42
|
@managers.each do |manager|
|
|
44
|
-
Concurrent::
|
|
45
|
-
log_manager_failure(ex)
|
|
46
|
-
start_soft_shutdown
|
|
47
|
-
end
|
|
43
|
+
Concurrent::Future.execute { manager.start }
|
|
48
44
|
end
|
|
49
45
|
end
|
|
50
46
|
|
|
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
47
|
def initiate_stop
|
|
63
48
|
logger.info { 'Shutting down' }
|
|
64
49
|
|
|
65
|
-
@managers.each(&:stop)
|
|
66
|
-
|
|
67
50
|
stop_callback
|
|
68
51
|
end
|
|
69
52
|
|
|
@@ -90,7 +73,8 @@ module Shoryuken
|
|
|
90
73
|
Shoryuken::Manager.new(
|
|
91
74
|
Shoryuken::Fetcher.new(group),
|
|
92
75
|
Shoryuken.polling_strategy(group).new(options[:queues]),
|
|
93
|
-
options[:concurrency]
|
|
76
|
+
options[:concurrency],
|
|
77
|
+
executor
|
|
94
78
|
)
|
|
95
79
|
end
|
|
96
80
|
end
|
data/lib/shoryuken/logging.rb
CHANGED
|
@@ -3,7 +3,6 @@ require 'logger'
|
|
|
3
3
|
|
|
4
4
|
module Shoryuken
|
|
5
5
|
module Logging
|
|
6
|
-
|
|
7
6
|
class Pretty < Logger::Formatter
|
|
8
7
|
# Provide a call() method that returns the formatted message.
|
|
9
8
|
def call(severity, time, program_name, message)
|
|
@@ -37,9 +36,5 @@ module Shoryuken
|
|
|
37
36
|
def self.logger=(log)
|
|
38
37
|
@logger = (log ? log : Logger.new('/dev/null'))
|
|
39
38
|
end
|
|
40
|
-
|
|
41
|
-
def logger
|
|
42
|
-
shoryuken::Logging.logger
|
|
43
|
-
end
|
|
44
39
|
end
|
|
45
40
|
end
|
data/lib/shoryuken/manager.rb
CHANGED
|
@@ -6,47 +6,47 @@ module Shoryuken
|
|
|
6
6
|
# See https://github.com/phstc/shoryuken/issues/348#issuecomment-292847028
|
|
7
7
|
MIN_DISPATCH_INTERVAL = 0.1
|
|
8
8
|
|
|
9
|
-
def initialize(fetcher, polling_strategy, concurrency)
|
|
9
|
+
def initialize(fetcher, polling_strategy, concurrency, executor)
|
|
10
10
|
@fetcher = fetcher
|
|
11
11
|
@polling_strategy = polling_strategy
|
|
12
12
|
@max_processors = concurrency
|
|
13
13
|
@busy_processors = Concurrent::AtomicFixnum.new(0)
|
|
14
|
-
@
|
|
14
|
+
@executor = executor
|
|
15
|
+
@running = Concurrent::AtomicBoolean.new(true)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def start
|
|
18
|
-
|
|
19
|
+
dispatch_loop
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def running?
|
|
25
|
+
@running.true? && @executor.running?
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
|
|
28
|
+
def dispatch_loop
|
|
29
|
+
return unless running?
|
|
26
30
|
|
|
27
|
-
|
|
28
|
-
@done.true? || !Concurrent.global_io_executor.running?
|
|
31
|
+
@executor.post { dispatch }
|
|
29
32
|
end
|
|
30
33
|
|
|
31
34
|
def dispatch
|
|
32
|
-
return
|
|
35
|
+
return unless running?
|
|
33
36
|
|
|
34
|
-
if
|
|
35
|
-
return
|
|
37
|
+
if ready <= 0 || (queue = @polling_strategy.next_queue).nil?
|
|
38
|
+
return sleep(MIN_DISPATCH_INTERVAL)
|
|
36
39
|
end
|
|
37
40
|
|
|
38
|
-
fire_event(:dispatch)
|
|
41
|
+
fire_event(:dispatch, false, queue_name: queue.name)
|
|
39
42
|
|
|
40
|
-
logger.
|
|
43
|
+
logger.debug { "Ready: #{ready}, Busy: #{busy}, Active Queues: #{@polling_strategy.active_queues}" }
|
|
41
44
|
|
|
42
45
|
batched_queue?(queue) ? dispatch_batch(queue) : dispatch_single_messages(queue)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def dispatch_later
|
|
48
|
-
sleep(MIN_DISPATCH_INTERVAL)
|
|
49
|
-
dispatch
|
|
46
|
+
rescue => ex
|
|
47
|
+
handle_dispatch_error(ex)
|
|
48
|
+
ensure
|
|
49
|
+
dispatch_loop
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def busy
|
|
@@ -62,15 +62,15 @@ module Shoryuken
|
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
def assign(queue_name, sqs_msg)
|
|
65
|
-
return
|
|
65
|
+
return unless running?
|
|
66
66
|
|
|
67
67
|
logger.debug { "Assigning #{sqs_msg.message_id}" }
|
|
68
68
|
|
|
69
69
|
@busy_processors.increment
|
|
70
70
|
|
|
71
|
-
Concurrent::Promise.execute
|
|
72
|
-
|
|
73
|
-
}.then { processor_done }.rescue { processor_done }
|
|
71
|
+
Concurrent::Promise.execute(
|
|
72
|
+
executor: @executor
|
|
73
|
+
) { Processor.process(queue_name, sqs_msg) }.then { processor_done }.rescue { processor_done }
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
def dispatch_batch(queue)
|
|
@@ -99,5 +99,14 @@ module Shoryuken
|
|
|
99
99
|
|
|
100
100
|
sqs_msgs
|
|
101
101
|
end
|
|
102
|
+
|
|
103
|
+
def handle_dispatch_error(ex)
|
|
104
|
+
logger.error { "Manager failed: #{ex.message}" }
|
|
105
|
+
logger.error { ex.backtrace.join("\n") } unless ex.backtrace.nil?
|
|
106
|
+
|
|
107
|
+
Process.kill('USR1', Process.pid)
|
|
108
|
+
|
|
109
|
+
@running.make_false
|
|
110
|
+
end
|
|
102
111
|
end
|
|
103
112
|
end
|
|
@@ -61,6 +61,10 @@ module Shoryuken
|
|
|
61
61
|
entries << Entry.new(klass, *args) unless exists?(klass)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
+
def prepend(klass, *args)
|
|
65
|
+
entries.insert(0, Entry.new(klass, *args)) unless exists?(klass)
|
|
66
|
+
end
|
|
67
|
+
|
|
64
68
|
def insert_before(oldklass, newklass, *args)
|
|
65
69
|
i = entries.index { |entry| entry.klass == newklass }
|
|
66
70
|
new_entry = i.nil? ? Entry.new(newklass, *args) : entries.delete_at(i)
|
|
@@ -31,16 +31,13 @@ module Shoryuken
|
|
|
31
31
|
Concurrent::TimerTask.new(execution_interval: queue_visibility_timeout - EXTEND_UPFRONT_SECONDS) do
|
|
32
32
|
begin
|
|
33
33
|
logger.debug do
|
|
34
|
-
"Extending message #{
|
|
35
|
-
"visibility timeout by #{queue_visibility_timeout}s."
|
|
34
|
+
"Extending message #{queue}/#{sqs_msg.message_id} visibility timeout by #{queue_visibility_timeout}s"
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
sqs_msg.change_visibility(visibility_timeout: queue_visibility_timeout)
|
|
39
38
|
rescue => ex
|
|
40
39
|
logger.error do
|
|
41
|
-
|
|
42
|
-
"#{worker_name(worker.class, sqs_msg, body)}/#{queue}/#{sqs_msg.message_id} " \
|
|
43
|
-
"visibility timeout. Error: #{ex.message}"
|
|
40
|
+
"Could not auto extend the message #{queue}/#{sqs_msg.message_id} visibility timeout. Error: #{ex.message}"
|
|
44
41
|
end
|
|
45
42
|
end
|
|
46
43
|
end
|
|
@@ -5,25 +5,23 @@ module Shoryuken
|
|
|
5
5
|
include Util
|
|
6
6
|
|
|
7
7
|
def call(worker, queue, sqs_msg, body)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
started_at = Time.now
|
|
8
|
+
begin
|
|
9
|
+
started_at = Time.now
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
logger.info { "started at #{started_at}" }
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
yield
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
total_time = elapsed(started_at)
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
logger.info { "completed in: #{total_time} ms" }
|
|
23
|
-
rescue
|
|
24
|
-
logger.info { "failed in: #{elapsed(started_at)} ms" }
|
|
25
|
-
raise
|
|
17
|
+
if (total_time / 1000.0) > (timeout = Shoryuken::Client.queues(queue).visibility_timeout)
|
|
18
|
+
logger.warn { "exceeded the queue visibility timeout by #{total_time - (timeout * 1000)} ms" }
|
|
26
19
|
end
|
|
20
|
+
|
|
21
|
+
logger.info { "completed in: #{total_time} ms" }
|
|
22
|
+
rescue
|
|
23
|
+
logger.info { "failed in: #{elapsed(started_at)} ms" }
|
|
24
|
+
raise
|
|
27
25
|
end
|
|
28
26
|
end
|
|
29
27
|
end
|