shoryuken 3.0.11 → 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.
@@ -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