shoryuken 3.0.9 → 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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +24 -0
- data/Gemfile +1 -0
- data/README.md +15 -110
- data/bin/cli/sqs.rb +15 -1
- data/lib/shoryuken/default_worker_registry.rb +2 -2
- data/lib/shoryuken/environment_loader.rb +31 -11
- data/lib/shoryuken/fetcher.rb +17 -16
- data/lib/shoryuken/launcher.rb +86 -7
- data/lib/shoryuken/manager.rb +38 -79
- data/lib/shoryuken/options.rb +192 -0
- data/lib/shoryuken/polling/base.rb +67 -0
- data/lib/shoryuken/polling/strict_priority.rb +77 -0
- data/lib/shoryuken/polling/weighted_round_robin.rb +66 -0
- data/lib/shoryuken/processor.rb +21 -18
- data/lib/shoryuken/queue.rb +12 -11
- data/lib/shoryuken/runner.rb +3 -15
- data/lib/shoryuken/version.rb +1 -1
- data/lib/shoryuken.rb +39 -173
- data/shoryuken.gemspec +1 -1
- data/spec/integration/launcher_spec.rb +12 -6
- data/spec/shoryuken/environment_loader_spec.rb +3 -12
- data/spec/shoryuken/fetcher_spec.rb +30 -15
- data/spec/shoryuken/manager_spec.rb +9 -17
- data/spec/shoryuken/options_spec.rb +100 -0
- data/spec/shoryuken/{polling_spec.rb → polling/strict_priority_spec.rb} +1 -100
- data/spec/shoryuken/polling/weighted_round_robin_spec.rb +99 -0
- data/spec/shoryuken/processor_spec.rb +20 -39
- data/spec/shoryuken/queue_spec.rb +8 -0
- data/spec/shoryuken/runner_spec.rb +3 -4
- data/spec/shoryuken_spec.rb +0 -59
- data/spec/spec_helper.rb +7 -2
- metadata +14 -7
- data/lib/shoryuken/polling.rb +0 -204
data/lib/shoryuken.rb
CHANGED
|
@@ -20,185 +20,51 @@ require 'shoryuken/middleware/server/auto_delete'
|
|
|
20
20
|
Shoryuken::Middleware::Server.autoload :AutoExtendVisibility, 'shoryuken/middleware/server/auto_extend_visibility'
|
|
21
21
|
require 'shoryuken/middleware/server/exponential_backoff_retry'
|
|
22
22
|
require 'shoryuken/middleware/server/timing'
|
|
23
|
-
require 'shoryuken/polling'
|
|
23
|
+
require 'shoryuken/polling/base'
|
|
24
|
+
require 'shoryuken/polling/weighted_round_robin'
|
|
25
|
+
require 'shoryuken/polling/strict_priority'
|
|
24
26
|
require 'shoryuken/manager'
|
|
25
27
|
require 'shoryuken/launcher'
|
|
26
28
|
require 'shoryuken/processor'
|
|
27
29
|
require 'shoryuken/fetcher'
|
|
30
|
+
require 'shoryuken/options'
|
|
28
31
|
|
|
29
32
|
module Shoryuken
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def worker_registry=(worker_registry)
|
|
67
|
-
@@worker_registry = worker_registry
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def start_callback
|
|
71
|
-
@@start_callback
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def start_callback=(start_callback)
|
|
75
|
-
@@start_callback = start_callback
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def stop_callback
|
|
79
|
-
@@stop_callback
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def stop_callback=(stop_callback)
|
|
83
|
-
@@stop_callback = stop_callback
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def active_job_queue_name_prefixing
|
|
87
|
-
@@active_job_queue_name_prefixing
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def active_job_queue_name_prefixing=(active_job_queue_name_prefixing)
|
|
91
|
-
@@active_job_queue_name_prefixing = active_job_queue_name_prefixing
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def sqs_client
|
|
95
|
-
@@sqs_client ||= Aws::SQS::Client.new
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def sqs_client=(sqs_client)
|
|
99
|
-
@@sqs_client = sqs_client
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def sqs_client_receive_message_opts
|
|
103
|
-
@@sqs_client_receive_message_opts
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def sqs_client_receive_message_opts=(sqs_client_receive_message_opts)
|
|
107
|
-
@@sqs_client_receive_message_opts = sqs_client_receive_message_opts
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def options
|
|
111
|
-
@@options ||= DEFAULTS.dup
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def logger
|
|
115
|
-
Shoryuken::Logging.logger
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def register_worker(*args)
|
|
119
|
-
@@worker_registry.register_worker(*args)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def configure_server
|
|
123
|
-
yield self if server?
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def server_middleware
|
|
127
|
-
@@server_chain ||= default_server_middleware
|
|
128
|
-
yield @@server_chain if block_given?
|
|
129
|
-
@@server_chain
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def configure_client
|
|
133
|
-
yield self unless server?
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def client_middleware
|
|
137
|
-
@@client_chain ||= default_client_middleware
|
|
138
|
-
yield @@client_chain if block_given?
|
|
139
|
-
@@client_chain
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def default_worker_options
|
|
143
|
-
@@default_worker_options ||= {
|
|
144
|
-
'queue' => 'default',
|
|
145
|
-
'delete' => false,
|
|
146
|
-
'auto_delete' => false,
|
|
147
|
-
'auto_visibility_timeout' => false,
|
|
148
|
-
'retry_intervals' => nil,
|
|
149
|
-
'batch' => false
|
|
150
|
-
}
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
def default_worker_options=(default_worker_options)
|
|
154
|
-
@@default_worker_options = default_worker_options
|
|
155
|
-
end
|
|
156
|
-
|
|
157
|
-
def on_start(&block)
|
|
158
|
-
@@start_callback = block
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
def on_stop(&block)
|
|
162
|
-
@@stop_callback = block
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
# Register a block to run at a point in the Shoryuken lifecycle.
|
|
166
|
-
# :startup, :quiet or :shutdown are valid events.
|
|
167
|
-
#
|
|
168
|
-
# Shoryuken.configure_server do |config|
|
|
169
|
-
# config.on(:shutdown) do
|
|
170
|
-
# puts "Goodbye cruel world!"
|
|
171
|
-
# end
|
|
172
|
-
# end
|
|
173
|
-
def on(event, &block)
|
|
174
|
-
fail ArgumentError, "Symbols only please: #{event}" unless event.is_a?(Symbol)
|
|
175
|
-
fail ArgumentError, "Invalid event name: #{event}" unless options[:lifecycle_events].key?(event)
|
|
176
|
-
options[:lifecycle_events][event] << block
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
private
|
|
180
|
-
|
|
181
|
-
def default_server_middleware
|
|
182
|
-
Middleware::Chain.new do |m|
|
|
183
|
-
m.add Middleware::Server::Timing
|
|
184
|
-
m.add Middleware::Server::ExponentialBackoffRetry
|
|
185
|
-
m.add Middleware::Server::AutoDelete
|
|
186
|
-
m.add Middleware::Server::AutoExtendVisibility
|
|
187
|
-
if defined?(::ActiveRecord::Base)
|
|
188
|
-
require 'shoryuken/middleware/server/active_record'
|
|
189
|
-
m.add Middleware::Server::ActiveRecord
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
end
|
|
193
|
-
|
|
194
|
-
def default_client_middleware
|
|
195
|
-
Middleware::Chain.new
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def server?
|
|
199
|
-
defined?(Shoryuken::CLI)
|
|
200
|
-
end
|
|
201
|
-
end
|
|
33
|
+
extend SingleForwardable
|
|
34
|
+
|
|
35
|
+
def_delegators(
|
|
36
|
+
:'Shoryuken::Options',
|
|
37
|
+
:add_group,
|
|
38
|
+
:groups,
|
|
39
|
+
:add_queue,
|
|
40
|
+
:ungrouped_queues,
|
|
41
|
+
:worker_registry,
|
|
42
|
+
:worker_registry=,
|
|
43
|
+
:polling_strategy,
|
|
44
|
+
:start_callback,
|
|
45
|
+
:start_callback=,
|
|
46
|
+
:stop_callback,
|
|
47
|
+
:stop_callback=,
|
|
48
|
+
:active_job_queue_name_prefixing,
|
|
49
|
+
:active_job_queue_name_prefixing=,
|
|
50
|
+
:sqs_client,
|
|
51
|
+
:sqs_client=,
|
|
52
|
+
:sqs_client_receive_message_opts,
|
|
53
|
+
:sqs_client_receive_message_opts=,
|
|
54
|
+
:options,
|
|
55
|
+
:logger,
|
|
56
|
+
:register_worker,
|
|
57
|
+
:configure_server,
|
|
58
|
+
:server?,
|
|
59
|
+
:server_middleware,
|
|
60
|
+
:configure_client,
|
|
61
|
+
:client_middleware,
|
|
62
|
+
:default_worker_options,
|
|
63
|
+
:default_worker_options=,
|
|
64
|
+
:on_start,
|
|
65
|
+
:on_stop,
|
|
66
|
+
:on
|
|
67
|
+
)
|
|
202
68
|
end
|
|
203
69
|
|
|
204
70
|
require 'shoryuken/extensions/active_job_adapter' if defined?(::ActiveJob)
|
data/shoryuken.gemspec
CHANGED
|
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
|
|
|
23
23
|
spec.add_development_dependency 'pry-byebug'
|
|
24
24
|
spec.add_development_dependency 'dotenv'
|
|
25
25
|
|
|
26
|
-
spec.add_dependency 'aws-sdk-core', '
|
|
26
|
+
spec.add_dependency 'aws-sdk-core', '> 2'
|
|
27
27
|
spec.add_dependency 'concurrent-ruby'
|
|
28
28
|
spec.add_dependency 'thor'
|
|
29
29
|
end
|
|
@@ -6,25 +6,31 @@ require 'securerandom'
|
|
|
6
6
|
RSpec.describe Shoryuken::Launcher do
|
|
7
7
|
describe 'Consuming messages', slow: :true do
|
|
8
8
|
before do
|
|
9
|
+
Aws.config[:stub_responses] = false
|
|
10
|
+
Aws.config[:region] = 'us-east-1'
|
|
11
|
+
|
|
9
12
|
StandardWorker.received_messages = 0
|
|
10
13
|
|
|
11
|
-
queue = "
|
|
14
|
+
queue = "shoryuken-travis-#{StandardWorker}-#{SecureRandom.uuid}"
|
|
12
15
|
|
|
13
|
-
Shoryuken::Client.sqs.create_queue
|
|
16
|
+
Shoryuken::Client.sqs.create_queue(queue_name: queue)
|
|
14
17
|
|
|
15
|
-
Shoryuken.
|
|
18
|
+
Shoryuken.add_group('default', 1)
|
|
19
|
+
Shoryuken.add_queue(queue, 1, 'default')
|
|
16
20
|
|
|
17
21
|
StandardWorker.get_shoryuken_options['queue'] = queue
|
|
18
22
|
|
|
19
|
-
Shoryuken.register_worker
|
|
23
|
+
Shoryuken.register_worker(queue, StandardWorker)
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
after do
|
|
27
|
+
Aws.config[:stub_responses] = true
|
|
28
|
+
|
|
23
29
|
queue_url = Shoryuken::Client.sqs.get_queue_url(
|
|
24
30
|
queue_name: StandardWorker.get_shoryuken_options['queue']
|
|
25
31
|
).queue_url
|
|
26
32
|
|
|
27
|
-
Shoryuken::Client.sqs.delete_queue
|
|
33
|
+
Shoryuken::Client.sqs.delete_queue(queue_url: queue_url)
|
|
28
34
|
end
|
|
29
35
|
|
|
30
36
|
it 'consumes as a command worker' do
|
|
@@ -61,7 +67,7 @@ RSpec.describe Shoryuken::Launcher do
|
|
|
61
67
|
end
|
|
62
68
|
|
|
63
69
|
def poll_queues_until
|
|
64
|
-
subject.
|
|
70
|
+
subject.start
|
|
65
71
|
|
|
66
72
|
Timeout::timeout(10) do
|
|
67
73
|
begin
|
|
@@ -15,20 +15,11 @@ RSpec.describe Shoryuken::EnvironmentLoader do
|
|
|
15
15
|
allow(subject).to receive(:patch_deprecated_workers)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
Shoryuken.options[:queues] = ['
|
|
18
|
+
specify do
|
|
19
|
+
Shoryuken.options[:queues] = ['queue1', ['queue2', 2]]
|
|
20
20
|
subject.load
|
|
21
21
|
|
|
22
|
-
expect(Shoryuken.queues).to eq(%w(
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
context 'with priority' do
|
|
26
|
-
it 'parses' do
|
|
27
|
-
Shoryuken.options[:queues] = ['queue_1', ['queue_2', 2]]
|
|
28
|
-
subject.load
|
|
29
|
-
|
|
30
|
-
expect(Shoryuken.queues).to eq(%w(queue_1 queue_2 queue_2))
|
|
31
|
-
end
|
|
22
|
+
expect(Shoryuken.groups['default'][:queues]).to eq(%w(queue1 queue2 queue2))
|
|
32
23
|
end
|
|
33
24
|
end
|
|
34
25
|
end
|
|
@@ -2,36 +2,51 @@ require 'spec_helper'
|
|
|
2
2
|
require 'shoryuken/manager'
|
|
3
3
|
require 'shoryuken/fetcher'
|
|
4
4
|
|
|
5
|
-
describe Shoryuken::Fetcher do
|
|
6
|
-
let(:queue)
|
|
7
|
-
let(:queue_name)
|
|
5
|
+
RSpec.describe Shoryuken::Fetcher do
|
|
6
|
+
let(:queue) { instance_double('Shoryuken::Queue') }
|
|
7
|
+
let(:queue_name) { 'default' }
|
|
8
8
|
let(:queue_config) { Shoryuken::Polling::QueueConfiguration.new(queue_name, {}) }
|
|
9
|
+
let(:group) { 'default' }
|
|
9
10
|
|
|
10
11
|
let(:sqs_msg) do
|
|
11
|
-
double(
|
|
12
|
+
double(
|
|
13
|
+
Shoryuken::Message,
|
|
12
14
|
queue_url: queue_name,
|
|
13
15
|
body: 'test',
|
|
14
16
|
message_id: 'fc754df79cc24c4196ca5996a44b771e',
|
|
15
|
-
|
|
17
|
+
)
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
subject { described_class.new }
|
|
20
|
+
subject { described_class.new(group) }
|
|
19
21
|
|
|
20
22
|
describe '#fetch' do
|
|
21
|
-
|
|
23
|
+
let(:limit) { 1 }
|
|
24
|
+
|
|
25
|
+
specify do
|
|
22
26
|
expect(Shoryuken::Client).to receive(:queues).with(queue_name).and_return(queue)
|
|
27
|
+
|
|
28
|
+
Shoryuken.sqs_client_receive_message_opts[group] = { wait_time_seconds: 10 }
|
|
29
|
+
|
|
23
30
|
expect(queue).to receive(:receive_messages).
|
|
24
|
-
with(max_number_of_messages:
|
|
31
|
+
with(wait_time_seconds: 10, max_number_of_messages: limit, message_attribute_names: ['All'], attribute_names: ['All']).
|
|
25
32
|
and_return([])
|
|
26
|
-
|
|
33
|
+
|
|
34
|
+
subject.fetch(queue_config, limit)
|
|
27
35
|
end
|
|
28
36
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
37
|
+
context 'when limit is greater than FETCH_LIMIT' do
|
|
38
|
+
let(:limit) { 20 }
|
|
39
|
+
|
|
40
|
+
specify do
|
|
41
|
+
Shoryuken.sqs_client_receive_message_opts[group] = {}
|
|
42
|
+
|
|
43
|
+
allow(Shoryuken::Client).to receive(:queues).with(queue_name).and_return(queue)
|
|
44
|
+
expect(queue).to receive(:receive_messages).
|
|
45
|
+
with(max_number_of_messages: described_class::FETCH_LIMIT, attribute_names: ['All'], message_attribute_names: ['All']).
|
|
46
|
+
and_return([])
|
|
47
|
+
|
|
48
|
+
subject.fetch(queue_config, limit)
|
|
49
|
+
end
|
|
35
50
|
end
|
|
36
51
|
end
|
|
37
52
|
end
|
|
@@ -11,28 +11,20 @@ RSpec.describe Shoryuken::Manager do
|
|
|
11
11
|
let(:queue) { 'default' }
|
|
12
12
|
let(:queues) { [queue] }
|
|
13
13
|
let(:polling_strategy) { Shoryuken::Polling::WeightedRoundRobin.new(queues) }
|
|
14
|
-
let(:fetcher) { Shoryuken::Fetcher
|
|
14
|
+
let(:fetcher) { double Shoryuken::Fetcher }
|
|
15
15
|
let(:concurrency) { 1 }
|
|
16
16
|
|
|
17
|
-
subject { Shoryuken::Manager.new(fetcher, polling_strategy) }
|
|
17
|
+
subject { Shoryuken::Manager.new(fetcher, polling_strategy, concurrency) }
|
|
18
18
|
|
|
19
|
-
before
|
|
20
|
-
|
|
19
|
+
before do
|
|
20
|
+
allow(fetcher).to receive(:fetch).and_return([])
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
after
|
|
23
|
+
after do
|
|
24
24
|
Shoryuken.options[:concurrency] = 1
|
|
25
25
|
TestWorker.get_shoryuken_options['batch'] = false
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
describe 'Invalid concurrency setting' do
|
|
29
|
-
it 'raises ArgumentError if concurrency is not positive number' do
|
|
30
|
-
Shoryuken.options[:concurrency] = -1
|
|
31
|
-
expect { Shoryuken::Manager.new(nil, nil) }
|
|
32
|
-
.to raise_error(ArgumentError, 'Concurrency value -1 is invalid, it needs to be a positive number')
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
28
|
describe '#start' do
|
|
37
29
|
xit 'pauses when there are no active queues' do
|
|
38
30
|
expect(polling_strategy).to receive(:next_queue).and_return(nil)
|
|
@@ -55,10 +47,10 @@ RSpec.describe Shoryuken::Manager do
|
|
|
55
47
|
end
|
|
56
48
|
end
|
|
57
49
|
|
|
58
|
-
describe '#
|
|
59
|
-
|
|
60
|
-
expect(subject).to receive(:fire_event).with(:dispatch)
|
|
61
|
-
subject.send(:
|
|
50
|
+
describe '#dispatch' do
|
|
51
|
+
xit 'fires a dispatch event' do
|
|
52
|
+
expect(subject).to receive(:fire_event).with(:dispatch)
|
|
53
|
+
subject.send(:dispatch)
|
|
62
54
|
end
|
|
63
55
|
end
|
|
64
56
|
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Shoryuken::Options do
|
|
4
|
+
describe '.add_group' do
|
|
5
|
+
before do
|
|
6
|
+
Shoryuken.groups.clear
|
|
7
|
+
Shoryuken.add_group('group1', 25)
|
|
8
|
+
Shoryuken.add_group('group2', 25)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
specify do
|
|
12
|
+
described_class.add_queue('queue1', 1, 'group1')
|
|
13
|
+
described_class.add_queue('queue2', 2, 'group2')
|
|
14
|
+
|
|
15
|
+
expect(described_class.groups['group1'][:queues]).to eq(%w(queue1))
|
|
16
|
+
expect(described_class.groups['group2'][:queues]).to eq(%w(queue2 queue2))
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe '.ungrouped_queues' do
|
|
21
|
+
before do
|
|
22
|
+
Shoryuken.groups.clear
|
|
23
|
+
Shoryuken.add_group('group1', 25)
|
|
24
|
+
Shoryuken.add_group('group2', 25)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
specify do
|
|
28
|
+
described_class.add_queue('queue1', 1, 'group1')
|
|
29
|
+
described_class.add_queue('queue2', 2, 'group2')
|
|
30
|
+
|
|
31
|
+
expect(described_class.ungrouped_queues).to eq(%w(queue1 queue2 queue2))
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe '.sqs_client_receive_message_opts' do
|
|
36
|
+
before do
|
|
37
|
+
Shoryuken.sqs_client_receive_message_opts
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
specify do
|
|
41
|
+
Shoryuken.sqs_client_receive_message_opts = { test: 1 }
|
|
42
|
+
expect(Shoryuken.sqs_client_receive_message_opts).to eq('default' => { test: 1 })
|
|
43
|
+
|
|
44
|
+
Shoryuken.sqs_client_receive_message_opts['group1'] = { test: 2 }
|
|
45
|
+
|
|
46
|
+
expect(Shoryuken.sqs_client_receive_message_opts).to eq(
|
|
47
|
+
'default' => { test: 1 },
|
|
48
|
+
'group1' => { test: 2 },
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe '.register_worker' do
|
|
54
|
+
it 'registers a worker' do
|
|
55
|
+
described_class.worker_registry.clear
|
|
56
|
+
described_class.register_worker('default', TestWorker)
|
|
57
|
+
expect(described_class.worker_registry.workers('default')).to eq([TestWorker])
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'registers a batchable worker' do
|
|
61
|
+
described_class.worker_registry.clear
|
|
62
|
+
TestWorker.get_shoryuken_options['batch'] = true
|
|
63
|
+
described_class.register_worker('default', TestWorker)
|
|
64
|
+
expect(described_class.worker_registry.workers('default')).to eq([TestWorker])
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'allows multiple workers' do
|
|
68
|
+
described_class.worker_registry.clear
|
|
69
|
+
described_class.register_worker('default', TestWorker)
|
|
70
|
+
expect(described_class.worker_registry.workers('default')).to eq([TestWorker])
|
|
71
|
+
|
|
72
|
+
class Test2Worker
|
|
73
|
+
include Shoryuken::Worker
|
|
74
|
+
|
|
75
|
+
shoryuken_options queue: 'default'
|
|
76
|
+
|
|
77
|
+
def perform(sqs_msg, body); end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
expect(described_class.worker_registry.workers('default')).to eq([Test2Worker])
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it 'raises an exception when mixing batchable with non batchable' do
|
|
84
|
+
described_class.worker_registry.clear
|
|
85
|
+
TestWorker.get_shoryuken_options['batch'] = true
|
|
86
|
+
described_class.register_worker('default', TestWorker)
|
|
87
|
+
|
|
88
|
+
expect {
|
|
89
|
+
class BatchableWorker
|
|
90
|
+
include Shoryuken::Worker
|
|
91
|
+
|
|
92
|
+
shoryuken_options queue: 'default', batch: true
|
|
93
|
+
|
|
94
|
+
def perform(sqs_msg, body); end
|
|
95
|
+
end
|
|
96
|
+
}.to raise_error("Could not register BatchableWorker for default, because TestWorker is already registered for this queue, " \
|
|
97
|
+
"and Shoryuken doesn't support a batchable worker for a queue with multiple workers")
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -1,105 +1,6 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'shoryuken/polling'
|
|
3
2
|
|
|
4
|
-
describe Shoryuken::Polling::
|
|
5
|
-
let(:queue1) { 'shoryuken' }
|
|
6
|
-
let(:queue2) { 'uppercut' }
|
|
7
|
-
let(:queues) { Array.new }
|
|
8
|
-
subject { Shoryuken::Polling::WeightedRoundRobin.new(queues) }
|
|
9
|
-
|
|
10
|
-
describe '#next_queue' do
|
|
11
|
-
it 'cycles' do
|
|
12
|
-
# [shoryuken, 2]
|
|
13
|
-
# [uppercut, 1]
|
|
14
|
-
queues << queue1
|
|
15
|
-
queues << queue1
|
|
16
|
-
queues << queue2
|
|
17
|
-
|
|
18
|
-
expect(subject.next_queue).to eq(queue1)
|
|
19
|
-
expect(subject.next_queue).to eq(queue2)
|
|
20
|
-
expect(subject.next_queue).to eq(queue1)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
it 'returns nil if there are no active queues' do
|
|
24
|
-
expect(subject.next_queue).to eq(nil)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
it 'unpauses queues whose pause is expired' do
|
|
28
|
-
# [shoryuken, 2]
|
|
29
|
-
# [uppercut, 1]
|
|
30
|
-
queues << queue1
|
|
31
|
-
queues << queue1
|
|
32
|
-
queues << queue2
|
|
33
|
-
|
|
34
|
-
allow(subject).to receive(:delay).and_return(10)
|
|
35
|
-
|
|
36
|
-
now = Time.now
|
|
37
|
-
allow(Time).to receive(:now).and_return(now)
|
|
38
|
-
|
|
39
|
-
# pause the first queue
|
|
40
|
-
subject.messages_found(queue1, 0)
|
|
41
|
-
expect(subject.next_queue).to eq(queue2)
|
|
42
|
-
|
|
43
|
-
now += 5
|
|
44
|
-
allow(Time).to receive(:now).and_return(now)
|
|
45
|
-
|
|
46
|
-
# pause the second queue
|
|
47
|
-
subject.messages_found(queue2, 0)
|
|
48
|
-
expect(subject.next_queue).to eq(nil)
|
|
49
|
-
|
|
50
|
-
# queue1 should be unpaused now
|
|
51
|
-
now += 6
|
|
52
|
-
allow(Time).to receive(:now).and_return(now)
|
|
53
|
-
expect(subject.next_queue).to eq(queue1)
|
|
54
|
-
|
|
55
|
-
# queue1 should be unpaused and added to the end of queues now
|
|
56
|
-
now += 6
|
|
57
|
-
allow(Time).to receive(:now).and_return(now)
|
|
58
|
-
expect(subject.next_queue).to eq(queue1)
|
|
59
|
-
expect(subject.next_queue).to eq(queue2)
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
describe '#messages_found' do
|
|
64
|
-
it 'pauses a queue if there are no messages found' do
|
|
65
|
-
# [shoryuken, 2]
|
|
66
|
-
# [uppercut, 1]
|
|
67
|
-
queues << queue1
|
|
68
|
-
queues << queue1
|
|
69
|
-
queues << queue2
|
|
70
|
-
|
|
71
|
-
expect(subject).to receive(:pause).with(queue1).and_call_original
|
|
72
|
-
subject.messages_found(queue1, 0)
|
|
73
|
-
expect(subject.instance_variable_get(:@queues)).to eq([queue2])
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it 'increased the weight if message is found' do
|
|
77
|
-
# [shoryuken, 2]
|
|
78
|
-
# [uppercut, 1]
|
|
79
|
-
queues << queue1
|
|
80
|
-
queues << queue1
|
|
81
|
-
queues << queue2
|
|
82
|
-
|
|
83
|
-
expect(subject.instance_variable_get(:@queues)).to eq([queue1, queue2])
|
|
84
|
-
subject.messages_found(queue1, 1)
|
|
85
|
-
expect(subject.instance_variable_get(:@queues)).to eq([queue1, queue2, queue1])
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
it 'respects the maximum queue weight' do
|
|
89
|
-
# [shoryuken, 2]
|
|
90
|
-
# [uppercut, 1]
|
|
91
|
-
queues << queue1
|
|
92
|
-
queues << queue1
|
|
93
|
-
queues << queue2
|
|
94
|
-
|
|
95
|
-
subject.messages_found(queue1, 1)
|
|
96
|
-
subject.messages_found(queue1, 1)
|
|
97
|
-
expect(subject.instance_variable_get(:@queues)).to eq([queue1, queue2, queue1])
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
describe Shoryuken::Polling::StrictPriority do
|
|
3
|
+
RSpec.describe Shoryuken::Polling::StrictPriority do
|
|
103
4
|
let(:queue1) { 'shoryuken' }
|
|
104
5
|
let(:queue2) { 'uppercut' }
|
|
105
6
|
let(:queue3) { 'other' }
|