shoryuken 2.0.11 → 3.0.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/.codeclimate.yml +20 -0
- data/.rubocop.yml +8 -2
- data/.travis.yml +7 -5
- data/CHANGELOG.md +92 -10
- data/Gemfile +1 -0
- data/README.md +20 -57
- data/Rakefile +0 -1
- data/bin/cli/base.rb +42 -0
- data/bin/cli/sqs.rb +188 -0
- data/bin/shoryuken +47 -9
- data/examples/default_worker.rb +1 -12
- data/lib/shoryuken/client.rb +3 -25
- data/lib/shoryuken/default_worker_registry.rb +9 -5
- data/lib/shoryuken/environment_loader.rb +29 -67
- data/lib/shoryuken/fetcher.rb +22 -53
- data/lib/shoryuken/launcher.rb +5 -29
- data/lib/shoryuken/manager.rb +72 -184
- data/lib/shoryuken/message.rb +4 -13
- data/lib/shoryuken/middleware/chain.rb +1 -18
- data/lib/shoryuken/middleware/server/auto_extend_visibility.rb +21 -18
- data/lib/shoryuken/middleware/server/exponential_backoff_retry.rb +26 -19
- data/lib/shoryuken/polling.rb +204 -0
- data/lib/shoryuken/processor.rb +6 -14
- data/lib/shoryuken/queue.rb +36 -38
- data/lib/shoryuken/runner.rb +143 -0
- data/lib/shoryuken/util.rb +3 -9
- data/lib/shoryuken/version.rb +1 -1
- data/lib/shoryuken/worker.rb +1 -1
- data/lib/shoryuken.rb +78 -39
- data/shoryuken.gemspec +6 -6
- data/spec/integration/launcher_spec.rb +4 -3
- data/spec/shoryuken/client_spec.rb +2 -43
- data/spec/shoryuken/default_worker_registry_spec.rb +12 -10
- data/spec/shoryuken/environment_loader_spec.rb +34 -0
- data/spec/shoryuken/fetcher_spec.rb +18 -52
- data/spec/shoryuken/manager_spec.rb +56 -97
- data/spec/shoryuken/middleware/chain_spec.rb +0 -24
- data/spec/shoryuken/middleware/server/auto_delete_spec.rb +2 -2
- data/spec/shoryuken/middleware/server/auto_extend_visibility_spec.rb +7 -3
- data/spec/shoryuken/middleware/server/exponential_backoff_retry_spec.rb +56 -33
- data/spec/shoryuken/polling_spec.rb +239 -0
- data/spec/shoryuken/processor_spec.rb +5 -5
- data/spec/shoryuken/queue_spec.rb +110 -63
- data/spec/shoryuken/{cli_spec.rb → runner_spec.rb} +10 -24
- data/spec/shoryuken_spec.rb +13 -1
- data/spec/spec_helper.rb +8 -20
- data/test_workers/endless_interruptive_worker.rb +41 -0
- data/test_workers/endless_uninterruptive_worker.rb +44 -0
- metadata +34 -35
- data/.hound.yml +0 -6
- data/lib/shoryuken/cli.rb +0 -210
- data/lib/shoryuken/sns_arn.rb +0 -27
- data/lib/shoryuken/topic.rb +0 -17
- data/spec/shoryuken/sns_arn_spec.rb +0 -42
- data/spec/shoryuken/topic_spec.rb +0 -32
- data/spec/shoryuken_endpoint.yml +0 -6
- /data/{LICENSE.txt → LICENSE} +0 -0
|
@@ -44,28 +44,4 @@ describe Shoryuken::Middleware::Chain do
|
|
|
44
44
|
expect(final_action).to eq nil
|
|
45
45
|
expect(recorder).to eq []
|
|
46
46
|
end
|
|
47
|
-
|
|
48
|
-
class DeprecatedMiddleware
|
|
49
|
-
def call(worker_instance, queue, sqs_msg)
|
|
50
|
-
@@success = true
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def self.success?
|
|
54
|
-
!!@@success
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
it 'patches deprecated middleware' do
|
|
59
|
-
subject.clear
|
|
60
|
-
|
|
61
|
-
expect(Shoryuken.logger).to receive(:warn) do |&block|
|
|
62
|
-
expect(block.call).to eq('[DEPRECATION] DeprecatedMiddleware#call(worker_instance, queue, sqs_msg) is deprecated. Please use DeprecatedMiddleware#call(worker_instance, queue, sqs_msg, body)')
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
subject.add DeprecatedMiddleware
|
|
66
|
-
|
|
67
|
-
subject.invoke TestWorker, 'test', double('SQS msg', body: 'test'), 'test'
|
|
68
|
-
|
|
69
|
-
expect(DeprecatedMiddleware.success?).to eq true
|
|
70
|
-
end
|
|
71
47
|
end
|
|
@@ -55,8 +55,8 @@ describe Shoryuken::Middleware::Server::AutoDelete do
|
|
|
55
55
|
expect(sqs_queue).to_not receive(:delete_messages)
|
|
56
56
|
|
|
57
57
|
expect {
|
|
58
|
-
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise '
|
|
59
|
-
}.to raise_error(
|
|
58
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'failed' }
|
|
59
|
+
}.to raise_error('failed')
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
describe Shoryuken::Middleware::Server::AutoExtendVisibility do
|
|
3
|
+
RSpec.describe Shoryuken::Middleware::Server::AutoExtendVisibility do
|
|
4
4
|
let(:queue) { 'default' }
|
|
5
5
|
let(:visibility_timeout) { 3 }
|
|
6
6
|
let(:extend_upfront) { 1 }
|
|
@@ -12,8 +12,6 @@ describe Shoryuken::Middleware::Server::AutoExtendVisibility do
|
|
|
12
12
|
|
|
13
13
|
# We need to run our worker inside actor context.
|
|
14
14
|
class Runner
|
|
15
|
-
include Celluloid
|
|
16
|
-
|
|
17
15
|
def run_and_sleep(worker, queue, sqs_msg, interval)
|
|
18
16
|
Shoryuken::Middleware::Server::AutoExtendVisibility.new.call(worker, queue, sqs_msg, sqs_msg.body) do
|
|
19
17
|
sleep interval
|
|
@@ -34,6 +32,12 @@ describe Shoryuken::Middleware::Server::AutoExtendVisibility do
|
|
|
34
32
|
stub_const('Shoryuken::Middleware::Server::AutoExtendVisibility::EXTEND_UPFRONT_SECONDS', extend_upfront)
|
|
35
33
|
end
|
|
36
34
|
|
|
35
|
+
context 'when batch worker' do
|
|
36
|
+
it 'yields' do
|
|
37
|
+
expect { |b| subject.call(nil, nil, [], nil, &b) }.to yield_control
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
it 'extends message visibility if jobs takes a long time' do
|
|
38
42
|
TestWorker.get_shoryuken_options['auto_visibility_timeout'] = true
|
|
39
43
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# rubocop:disable Metrics/BlockLength, Metrics/BlockDelimiters
|
|
4
|
+
RSpec.describe Shoryuken::Middleware::Server::ExponentialBackoffRetry do
|
|
4
5
|
let(:queue) { 'default' }
|
|
5
6
|
let(:sqs_queue) { double Shoryuken::Queue }
|
|
6
7
|
let(:sqs_msg) { double Shoryuken::Message, queue_url: queue, body: 'test', receipt_handle: SecureRandom.uuid,
|
|
@@ -10,8 +11,14 @@ describe Shoryuken::Middleware::Server::ExponentialBackoffRetry do
|
|
|
10
11
|
allow(Shoryuken::Client).to receive(:queues).with(queue).and_return(sqs_queue)
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
context 'when
|
|
14
|
-
it '
|
|
14
|
+
context 'when batch worker' do
|
|
15
|
+
it 'yields' do
|
|
16
|
+
expect { |b| subject.call(nil, nil, [], nil, &b) }.to yield_control
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context 'when no exception' do
|
|
21
|
+
it 'does not retry' do
|
|
15
22
|
TestWorker.get_shoryuken_options['retry_intervals'] = [300, 1800]
|
|
16
23
|
|
|
17
24
|
expect(sqs_msg).not_to receive(:change_visibility)
|
|
@@ -20,62 +27,78 @@ describe Shoryuken::Middleware::Server::ExponentialBackoffRetry do
|
|
|
20
27
|
end
|
|
21
28
|
end
|
|
22
29
|
|
|
23
|
-
context 'when
|
|
30
|
+
context 'when an error' do
|
|
31
|
+
context "and retry_intervals isn't set" do
|
|
32
|
+
it 'does not retry' do
|
|
33
|
+
expect(sqs_msg).not_to receive(:change_visibility)
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
35
|
+
expect {
|
|
36
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'Error' }
|
|
37
|
+
}.to raise_error(RuntimeError, 'Error')
|
|
38
|
+
end
|
|
39
|
+
end
|
|
27
40
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
41
|
+
context 'and retry_intervals is a lambda' do
|
|
42
|
+
it 'retries' do
|
|
43
|
+
TestWorker.get_shoryuken_options['retry_intervals'] = ->(_attempts) { 500 }
|
|
44
|
+
|
|
45
|
+
allow(sqs_msg).to receive(:queue) { sqs_queue }
|
|
46
|
+
expect(sqs_msg).to receive(:change_visibility).with(visibility_timeout: 500)
|
|
47
|
+
|
|
48
|
+
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'failed' } }.not_to raise_error
|
|
49
|
+
end
|
|
31
50
|
end
|
|
32
51
|
|
|
33
|
-
|
|
34
|
-
|
|
52
|
+
context 'and retry_intervals is empty' do
|
|
53
|
+
it 'does not retry' do
|
|
54
|
+
TestWorker.get_shoryuken_options['retry_intervals'] = []
|
|
35
55
|
|
|
36
|
-
|
|
56
|
+
expect(sqs_msg).not_to receive(:change_visibility)
|
|
37
57
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
58
|
+
expect {
|
|
59
|
+
subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'Error' }
|
|
60
|
+
}.to raise_error(RuntimeError, 'Error')
|
|
61
|
+
end
|
|
41
62
|
end
|
|
42
63
|
|
|
43
|
-
it '
|
|
64
|
+
it 'uses first interval ' do
|
|
44
65
|
TestWorker.get_shoryuken_options['retry_intervals'] = [300, 1800]
|
|
45
66
|
|
|
46
|
-
allow(sqs_msg).to receive(:queue){ sqs_queue }
|
|
67
|
+
allow(sqs_msg).to receive(:queue) { sqs_queue }
|
|
47
68
|
expect(sqs_msg).to receive(:change_visibility).with(visibility_timeout: 300)
|
|
48
69
|
|
|
49
|
-
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise } }.not_to raise_error
|
|
70
|
+
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'failed' } }.not_to raise_error
|
|
50
71
|
end
|
|
51
72
|
|
|
52
|
-
it '
|
|
73
|
+
it 'uses matching interval' do
|
|
53
74
|
TestWorker.get_shoryuken_options['retry_intervals'] = [300, 1800]
|
|
54
75
|
|
|
55
|
-
allow(sqs_msg).to receive(:attributes){ {'ApproximateReceiveCount' => 2 } }
|
|
56
|
-
allow(sqs_msg).to receive(:queue){ sqs_queue }
|
|
76
|
+
allow(sqs_msg).to receive(:attributes) { { 'ApproximateReceiveCount' => 2 } }
|
|
77
|
+
allow(sqs_msg).to receive(:queue) { sqs_queue }
|
|
57
78
|
expect(sqs_msg).to receive(:change_visibility).with(visibility_timeout: 1800)
|
|
58
79
|
|
|
59
|
-
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise } }.not_to raise_error
|
|
80
|
+
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'failed' } }.not_to raise_error
|
|
60
81
|
end
|
|
61
82
|
|
|
62
|
-
|
|
63
|
-
|
|
83
|
+
context 'when attempts exceeds retry_intervals' do
|
|
84
|
+
it 'uses last interval' do
|
|
85
|
+
TestWorker.get_shoryuken_options['retry_intervals'] = [300, 1800]
|
|
64
86
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
allow(sqs_msg).to receive(:attributes) { { 'ApproximateReceiveCount' => 3 } }
|
|
88
|
+
allow(sqs_msg).to receive(:queue) { sqs_queue }
|
|
89
|
+
expect(sqs_msg).to receive(:change_visibility).with(visibility_timeout: 1800)
|
|
68
90
|
|
|
69
|
-
|
|
91
|
+
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'failed' } }.not_to raise_error
|
|
92
|
+
end
|
|
70
93
|
end
|
|
71
94
|
|
|
72
|
-
it 'limits the visibility timeout to 12 hours
|
|
73
|
-
TestWorker.get_shoryuken_options['retry_intervals'] = [
|
|
95
|
+
it 'limits the visibility timeout to 12 hours' do
|
|
96
|
+
TestWorker.get_shoryuken_options['retry_intervals'] = [86_400]
|
|
74
97
|
|
|
75
|
-
allow(sqs_msg).to receive(:queue){ sqs_queue }
|
|
76
|
-
expect(sqs_msg).to receive(:change_visibility).with(visibility_timeout:
|
|
98
|
+
allow(sqs_msg).to receive(:queue) { sqs_queue }
|
|
99
|
+
expect(sqs_msg).to receive(:change_visibility).with(visibility_timeout: 43_198)
|
|
77
100
|
|
|
78
|
-
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise } }.not_to raise_error
|
|
101
|
+
expect { subject.call(TestWorker.new, queue, sqs_msg, sqs_msg.body) { raise 'failed' } }.not_to raise_error
|
|
79
102
|
end
|
|
80
103
|
end
|
|
81
104
|
end
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'shoryuken/polling'
|
|
3
|
+
|
|
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
|
|
103
|
+
let(:queue1) { 'shoryuken' }
|
|
104
|
+
let(:queue2) { 'uppercut' }
|
|
105
|
+
let(:queue3) { 'other' }
|
|
106
|
+
let(:queues) { Array.new }
|
|
107
|
+
subject { Shoryuken::Polling::StrictPriority.new(queues) }
|
|
108
|
+
|
|
109
|
+
describe '#next_queue' do
|
|
110
|
+
it 'cycles when declared desc' do
|
|
111
|
+
# [shoryuken, 2]
|
|
112
|
+
# [uppercut, 1]
|
|
113
|
+
queues << queue1
|
|
114
|
+
queues << queue1
|
|
115
|
+
queues << queue2
|
|
116
|
+
|
|
117
|
+
expect(subject.next_queue).to eq(queue1)
|
|
118
|
+
expect(subject.next_queue).to eq(queue2)
|
|
119
|
+
expect(subject.next_queue).to eq(queue1)
|
|
120
|
+
expect(subject.next_queue).to eq(queue2)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'cycles when declared asc' do
|
|
124
|
+
# [uppercut, 1]
|
|
125
|
+
# [shoryuken, 2]
|
|
126
|
+
queues << queue2
|
|
127
|
+
queues << queue1
|
|
128
|
+
queues << queue1
|
|
129
|
+
|
|
130
|
+
expect(subject.next_queue).to eq(queue1)
|
|
131
|
+
expect(subject.next_queue).to eq(queue2)
|
|
132
|
+
expect(subject.next_queue).to eq(queue1)
|
|
133
|
+
expect(subject.next_queue).to eq(queue2)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it 'returns nil if there are no active queues' do
|
|
137
|
+
expect(subject.next_queue).to eq(nil)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it 'unpauses queues whose pause is expired' do
|
|
141
|
+
# [shoryuken, 3]
|
|
142
|
+
# [uppercut, 2]
|
|
143
|
+
# [other, 1]
|
|
144
|
+
queues << queue1
|
|
145
|
+
queues << queue1
|
|
146
|
+
queues << queue1
|
|
147
|
+
queues << queue2
|
|
148
|
+
queues << queue2
|
|
149
|
+
queues << queue3
|
|
150
|
+
|
|
151
|
+
allow(subject).to receive(:delay).and_return(10)
|
|
152
|
+
|
|
153
|
+
now = Time.now
|
|
154
|
+
allow(Time).to receive(:now).and_return(now)
|
|
155
|
+
|
|
156
|
+
# pause the second queue, see it loop between 1 and 3
|
|
157
|
+
subject.messages_found(queue2, 0)
|
|
158
|
+
expect(subject.next_queue).to eq(queue1)
|
|
159
|
+
expect(subject.next_queue).to eq(queue3)
|
|
160
|
+
expect(subject.next_queue).to eq(queue1)
|
|
161
|
+
|
|
162
|
+
now += 5
|
|
163
|
+
allow(Time).to receive(:now).and_return(now)
|
|
164
|
+
|
|
165
|
+
# pause the first queue, see it repeat 3
|
|
166
|
+
subject.messages_found(queue1, 0)
|
|
167
|
+
expect(subject.next_queue).to eq(queue3)
|
|
168
|
+
expect(subject.next_queue).to eq(queue3)
|
|
169
|
+
|
|
170
|
+
# pause the third queue, see it have nothing
|
|
171
|
+
subject.messages_found(queue3, 0)
|
|
172
|
+
expect(subject.next_queue).to eq(nil)
|
|
173
|
+
|
|
174
|
+
# unpause queue 2
|
|
175
|
+
now += 6
|
|
176
|
+
allow(Time).to receive(:now).and_return(now)
|
|
177
|
+
expect(subject.next_queue).to eq(queue2)
|
|
178
|
+
|
|
179
|
+
# unpause queues 1 and 3
|
|
180
|
+
now += 6
|
|
181
|
+
allow(Time).to receive(:now).and_return(now)
|
|
182
|
+
expect(subject.next_queue).to eq(queue1)
|
|
183
|
+
expect(subject.next_queue).to eq(queue2)
|
|
184
|
+
expect(subject.next_queue).to eq(queue3)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
describe '#messages_found' do
|
|
189
|
+
it 'pauses a queue if there are no messages found' do
|
|
190
|
+
# [shoryuken, 2]
|
|
191
|
+
# [uppercut, 1]
|
|
192
|
+
queues << queue1
|
|
193
|
+
queues << queue1
|
|
194
|
+
queues << queue2
|
|
195
|
+
|
|
196
|
+
expect(subject.active_queues).to eq([[queue1, 2], [queue2, 1]])
|
|
197
|
+
expect(subject).to receive(:pause).with(queue1).and_call_original
|
|
198
|
+
subject.messages_found(queue1, 0)
|
|
199
|
+
expect(subject.active_queues).to eq([[queue2, 1]])
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it 'continues to queue the highest priority queue if messages are found' do
|
|
203
|
+
# [shoryuken, 3]
|
|
204
|
+
# [uppercut, 2]
|
|
205
|
+
# [other, 1]
|
|
206
|
+
queues << queue1
|
|
207
|
+
queues << queue1
|
|
208
|
+
queues << queue1
|
|
209
|
+
queues << queue2
|
|
210
|
+
queues << queue2
|
|
211
|
+
queues << queue3
|
|
212
|
+
|
|
213
|
+
expect(subject.next_queue).to eq(queue1)
|
|
214
|
+
subject.messages_found(queue1, 1)
|
|
215
|
+
expect(subject.next_queue).to eq(queue1)
|
|
216
|
+
subject.messages_found(queue1, 1)
|
|
217
|
+
expect(subject.next_queue).to eq(queue1)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it 'resets the priorities if messages are found part way' do
|
|
221
|
+
# [shoryuken, 3]
|
|
222
|
+
# [uppercut, 2]
|
|
223
|
+
# [other, 1]
|
|
224
|
+
queues << queue1
|
|
225
|
+
queues << queue1
|
|
226
|
+
queues << queue1
|
|
227
|
+
queues << queue2
|
|
228
|
+
queues << queue2
|
|
229
|
+
queues << queue3
|
|
230
|
+
|
|
231
|
+
expect(subject.next_queue).to eq(queue1)
|
|
232
|
+
expect(subject.next_queue).to eq(queue2)
|
|
233
|
+
subject.messages_found(queue2, 1)
|
|
234
|
+
expect(subject.next_queue).to eq(queue1)
|
|
235
|
+
expect(subject.next_queue).to eq(queue2)
|
|
236
|
+
expect(subject.next_queue).to eq(queue3)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
end
|
|
@@ -169,7 +169,7 @@ RSpec.describe Shoryuken::Processor do
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
it 'invokes middleware' do
|
|
172
|
-
expect(manager).to receive(:processor_done).with(queue
|
|
172
|
+
expect(manager).to receive(:processor_done).with(queue)
|
|
173
173
|
|
|
174
174
|
expect_any_instance_of(WorkerCalledMiddlewareWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
|
175
175
|
expect_any_instance_of(WorkerCalledMiddlewareWorker).to receive(:called).with(sqs_msg, queue)
|
|
@@ -199,7 +199,7 @@ RSpec.describe Shoryuken::Processor do
|
|
|
199
199
|
end
|
|
200
200
|
|
|
201
201
|
it "doesn't invoke middleware" do
|
|
202
|
-
expect(manager).to receive(:processor_done).with(queue
|
|
202
|
+
expect(manager).to receive(:processor_done).with(queue)
|
|
203
203
|
|
|
204
204
|
expect_any_instance_of(WorkerCalledMiddlewareWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
|
205
205
|
expect_any_instance_of(WorkerCalledMiddlewareWorker).to_not receive(:called).with(sqs_msg, queue)
|
|
@@ -212,7 +212,7 @@ RSpec.describe Shoryuken::Processor do
|
|
|
212
212
|
it 'performs with delete' do
|
|
213
213
|
TestWorker.get_shoryuken_options['auto_delete'] = true
|
|
214
214
|
|
|
215
|
-
expect(manager).to receive(:processor_done).with(queue
|
|
215
|
+
expect(manager).to receive(:processor_done).with(queue)
|
|
216
216
|
|
|
217
217
|
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
|
218
218
|
|
|
@@ -224,7 +224,7 @@ RSpec.describe Shoryuken::Processor do
|
|
|
224
224
|
it 'performs without delete' do
|
|
225
225
|
TestWorker.get_shoryuken_options['auto_delete'] = false
|
|
226
226
|
|
|
227
|
-
expect(manager).to receive(:processor_done).with(queue
|
|
227
|
+
expect(manager).to receive(:processor_done).with(queue)
|
|
228
228
|
|
|
229
229
|
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
|
230
230
|
|
|
@@ -249,7 +249,7 @@ RSpec.describe Shoryuken::Processor do
|
|
|
249
249
|
it 'performs without delete' do
|
|
250
250
|
Shoryuken.worker_registry.clear # unregister TestWorker
|
|
251
251
|
|
|
252
|
-
expect(manager).to receive(:processor_done).with(queue
|
|
252
|
+
expect(manager).to receive(:processor_done).with(queue)
|
|
253
253
|
|
|
254
254
|
expect_any_instance_of(TestWorker).to receive(:perform).with(sqs_msg, sqs_msg.body)
|
|
255
255
|
|