shoryuken 3.0.11 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.new }
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(:each) do
20
- Shoryuken.options[:concurrency] = concurrency
19
+ before do
20
+ allow(fetcher).to receive(:fetch).and_return([])
21
21
  end
22
22
 
23
- after(:each) do
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 '#dispatch_now' do
59
- it 'fires a dispatch event' do
60
- expect(subject).to receive(:fire_event).with(:dispatch).once
61
- subject.send(:dispatch_now)
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::WeightedRoundRobin do
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' }
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Shoryuken::Polling::WeightedRoundRobin do
4
+ let(:queue1) { 'shoryuken' }
5
+ let(:queue2) { 'uppercut' }
6
+ let(:queues) { Array.new }
7
+ subject { Shoryuken::Polling::WeightedRoundRobin.new(queues) }
8
+
9
+ describe '#next_queue' do
10
+ it 'cycles' do
11
+ # [shoryuken, 2]
12
+ # [uppercut, 1]
13
+ queues << queue1
14
+ queues << queue1
15
+ queues << queue2
16
+
17
+ expect(subject.next_queue).to eq(queue1)
18
+ expect(subject.next_queue).to eq(queue2)
19
+ expect(subject.next_queue).to eq(queue1)
20
+ end
21
+
22
+ it 'returns nil if there are no active queues' do
23
+ expect(subject.next_queue).to eq(nil)
24
+ end
25
+
26
+ it 'unpauses queues whose pause is expired' do
27
+ # [shoryuken, 2]
28
+ # [uppercut, 1]
29
+ queues << queue1
30
+ queues << queue1
31
+ queues << queue2
32
+
33
+ allow(subject).to receive(:delay).and_return(10)
34
+
35
+ now = Time.now
36
+ allow(Time).to receive(:now).and_return(now)
37
+
38
+ # pause the first queue
39
+ subject.messages_found(queue1, 0)
40
+ expect(subject.next_queue).to eq(queue2)
41
+
42
+ now += 5
43
+ allow(Time).to receive(:now).and_return(now)
44
+
45
+ # pause the second queue
46
+ subject.messages_found(queue2, 0)
47
+ expect(subject.next_queue).to eq(nil)
48
+
49
+ # queue1 should be unpaused now
50
+ now += 6
51
+ allow(Time).to receive(:now).and_return(now)
52
+ expect(subject.next_queue).to eq(queue1)
53
+
54
+ # queue1 should be unpaused and added to the end of queues now
55
+ now += 6
56
+ allow(Time).to receive(:now).and_return(now)
57
+ expect(subject.next_queue).to eq(queue1)
58
+ expect(subject.next_queue).to eq(queue2)
59
+ end
60
+ end
61
+
62
+ describe '#messages_found' do
63
+ it 'pauses a queue if there are no messages found' do
64
+ # [shoryuken, 2]
65
+ # [uppercut, 1]
66
+ queues << queue1
67
+ queues << queue1
68
+ queues << queue2
69
+
70
+ expect(subject).to receive(:pause).with(queue1).and_call_original
71
+ subject.messages_found(queue1, 0)
72
+ expect(subject.instance_variable_get(:@queues)).to eq([queue2])
73
+ end
74
+
75
+ it 'increased the weight if message is found' do
76
+ # [shoryuken, 2]
77
+ # [uppercut, 1]
78
+ queues << queue1
79
+ queues << queue1
80
+ queues << queue2
81
+
82
+ expect(subject.instance_variable_get(:@queues)).to eq([queue1, queue2])
83
+ subject.messages_found(queue1, 1)
84
+ expect(subject.instance_variable_get(:@queues)).to eq([queue1, queue2, queue1])
85
+ end
86
+
87
+ it 'respects the maximum queue weight' do
88
+ # [shoryuken, 2]
89
+ # [uppercut, 1]
90
+ queues << queue1
91
+ queues << queue1
92
+ queues << queue2
93
+
94
+ subject.messages_found(queue1, 1)
95
+ subject.messages_found(queue1, 1)
96
+ expect(subject.instance_variable_get(:@queues)).to eq([queue1, queue2, queue1])
97
+ end
98
+ end
99
+ end
@@ -3,7 +3,7 @@ require 'shoryuken/processor'
3
3
  require 'shoryuken/manager'
4
4
 
5
5
  RSpec.describe Shoryuken::Processor do
6
- let(:manager) { double Shoryuken::Manager, processor_done: nil }
6
+ let(:manager) { double Shoryuken::Manager }
7
7
  let(:sqs_queue) { double Shoryuken::Queue, visibility_timeout: 30 }
8
8
  let(:queue) { 'default' }
9
9
 
@@ -16,14 +16,14 @@ RSpec.describe Shoryuken::Processor do
16
16
  receipt_handle: SecureRandom.uuid
17
17
  end
18
18
 
19
- subject { described_class.new(manager) }
20
-
21
19
  before do
22
20
  allow(manager).to receive(:async).and_return(manager)
23
21
  allow(manager).to receive(:real_thread)
24
22
  allow(Shoryuken::Client).to receive(:queues).with(queue).and_return(sqs_queue)
25
23
  end
26
24
 
25
+ subject { described_class.new(queue, sqs_msg) }
26
+
27
27
  describe '#process' do
28
28
  it 'parses the body into JSON' do
29
29
  TestWorker.get_shoryuken_options['body_parser'] = :json
@@ -34,7 +34,7 @@ RSpec.describe Shoryuken::Processor do
34
34
 
35
35
  allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
36
36
 
37
- subject.process(queue, sqs_msg)
37
+ subject.process
38
38
  end
39
39
 
40
40
  it 'parses the body calling the proc' do
@@ -44,7 +44,7 @@ RSpec.describe Shoryuken::Processor do
44
44
 
45
45
  allow(sqs_msg).to receive(:body).and_return('test')
46
46
 
47
- subject.process(queue, sqs_msg)
47
+ subject.process
48
48
  end
49
49
 
50
50
  it 'parses the body as text' do
@@ -56,7 +56,7 @@ RSpec.describe Shoryuken::Processor do
56
56
 
57
57
  allow(sqs_msg).to receive(:body).and_return(body)
58
58
 
59
- subject.process(queue, sqs_msg)
59
+ subject.process
60
60
  end
61
61
 
62
62
  it 'parses calling `.load`' do
@@ -72,7 +72,7 @@ RSpec.describe Shoryuken::Processor do
72
72
 
73
73
  allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
74
74
 
75
- subject.process(queue, sqs_msg)
75
+ subject.process
76
76
  end
77
77
 
78
78
  it 'parses calling `.parse`' do
@@ -88,30 +88,21 @@ RSpec.describe Shoryuken::Processor do
88
88
 
89
89
  allow(sqs_msg).to receive(:body).and_return(JSON.dump(body))
90
90
 
91
- subject.process(queue, sqs_msg)
91
+ subject.process
92
92
  end
93
93
 
94
94
  context 'when parse errors' do
95
95
  before do
96
96
  TestWorker.get_shoryuken_options['body_parser'] = :json
97
97
 
98
- allow(sqs_msg).to receive(:body).and_return('invalid json')
98
+ allow(sqs_msg).to receive(:body).and_return('invalid JSON')
99
99
  end
100
100
 
101
- it 'logs the error' do
102
- expect(manager).to receive(:processor_failed)
103
- expect(subject.logger).to receive(:error) do |&block|
104
- expect(block.call).
105
- to include("unexpected token at 'invalid json'\nbody_parser: json\nsqs_msg.body: invalid json")
106
- end
107
-
108
- subject.process(queue, sqs_msg) rescue nil
109
- end
101
+ specify do
102
+ expect(subject.logger).to receive(:error).twice
110
103
 
111
- it 're raises the error' do
112
- expect(manager).to receive(:processor_failed)
113
- expect { subject.process(queue, sqs_msg) }.
114
- to raise_error(JSON::ParserError, /unexpected token at 'invalid json'/)
104
+ expect { subject.process }.
105
+ to raise_error(JSON::ParserError, /unexpected token at 'invalid JSON'/)
115
106
  end
116
107
  end
117
108
 
@@ -125,7 +116,7 @@ RSpec.describe Shoryuken::Processor do
125
116
 
126
117
  allow(sqs_msg).to receive(:body).and_return(body)
127
118
 
128
- subject.process(queue, sqs_msg)
119
+ subject.process
129
120
  end
130
121
  end
131
122
 
@@ -152,7 +143,7 @@ RSpec.describe Shoryuken::Processor do
152
143
 
153
144
  context 'server' do
154
145
  before do
155
- allow(Shoryuken).to receive(:server?).and_return(true)
146
+ allow(Shoryuken::Options).to receive(:server?).and_return(true)
156
147
  WorkerCalledMiddlewareWorker.instance_variable_set(:@server_chain, nil) # un-memoize middleware
157
148
 
158
149
  Shoryuken.configure_server do |config|
@@ -171,12 +162,10 @@ RSpec.describe Shoryuken::Processor do
171
162
  end
172
163
 
173
164
  it 'invokes middleware' do
174
- expect(manager).to receive(:processor_done).with(queue)
175
-
176
165
  expect_any_instance_of(WorkerCalledMiddlewareWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
177
166
  expect_any_instance_of(WorkerCalledMiddlewareWorker).to receive(:called).with(sqs_msg, queue)
178
167
 
179
- subject.process(queue, sqs_msg)
168
+ subject.process
180
169
  end
181
170
  end
182
171
 
@@ -201,12 +190,10 @@ RSpec.describe Shoryuken::Processor do
201
190
  end
202
191
 
203
192
  it "doesn't invoke middleware" do
204
- expect(manager).to receive(:processor_done).with(queue)
205
-
206
193
  expect_any_instance_of(WorkerCalledMiddlewareWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
207
194
  expect_any_instance_of(WorkerCalledMiddlewareWorker).to_not receive(:called).with(sqs_msg, queue)
208
195
 
209
- subject.process(queue, sqs_msg)
196
+ subject.process
210
197
  end
211
198
  end
212
199
  end
@@ -214,25 +201,21 @@ RSpec.describe Shoryuken::Processor do
214
201
  it 'performs with delete' do
215
202
  TestWorker.get_shoryuken_options['auto_delete'] = true
216
203
 
217
- expect(manager).to receive(:processor_done).with(queue)
218
-
219
204
  expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
220
205
 
221
206
  expect(sqs_queue).to receive(:delete_messages).with(entries: [{ id: '0', receipt_handle: sqs_msg.receipt_handle }])
222
207
 
223
- subject.process(queue, sqs_msg)
208
+ subject.process
224
209
  end
225
210
 
226
211
  it 'performs without delete' do
227
212
  TestWorker.get_shoryuken_options['auto_delete'] = false
228
213
 
229
- expect(manager).to receive(:processor_done).with(queue)
230
-
231
214
  expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
232
215
 
233
216
  expect(sqs_queue).to_not receive(:delete_messages)
234
217
 
235
- subject.process(queue, sqs_msg)
218
+ subject.process
236
219
  end
237
220
 
238
221
  context 'when shoryuken_class header' do
@@ -251,13 +234,11 @@ RSpec.describe Shoryuken::Processor do
251
234
  it 'performs without delete' do
252
235
  Shoryuken.worker_registry.clear # unregister TestWorker
253
236
 
254
- expect(manager).to receive(:processor_done).with(queue)
255
-
256
237
  expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
257
238
 
258
239
  expect(sqs_queue).to_not receive(:delete_messages)
259
240
 
260
- subject.process(queue, sqs_msg)
241
+ subject.process
261
242
  end
262
243
  end
263
244
  end