message-driver 0.3.0 → 0.4.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 +18 -0
- data/.rubocop_todo.yml +160 -0
- data/.travis.yml +5 -4
- data/CHANGELOG.md +5 -0
- data/Gemfile +9 -8
- data/Guardfile +14 -7
- data/README.md +2 -0
- data/Rakefile +16 -10
- data/examples/basic_producer_and_consumer/Gemfile +2 -2
- data/examples/basic_producer_and_consumer/common.rb +3 -3
- data/examples/basic_producer_and_consumer/consumer.rb +5 -5
- data/examples/basic_producer_and_consumer/producer.rb +7 -7
- data/features/CHANGELOG.md +5 -0
- data/features/message_consumers/transactional_ack_consumers.feature +1 -0
- data/features/rabbitmq_specific_features/publisher_acknowledgements.feature +51 -0
- data/features/step_definitions/error_handling_steps.rb +2 -2
- data/features/step_definitions/logging_steps.rb +4 -4
- data/features/step_definitions/message_consumers_steps.rb +8 -8
- data/features/step_definitions/rabbitmq_specific_steps.rb +10 -0
- data/features/step_definitions/steps.rb +15 -15
- data/features/support/env.rb +3 -0
- data/features/support/firewall_helper.rb +5 -6
- data/features/support/message_table_matcher.rb +3 -4
- data/features/support/no_error_matcher.rb +3 -3
- data/features/support/test_runner.rb +11 -3
- data/features/support/transforms.rb +1 -1
- data/lib/message-driver.rb +1 -1
- data/lib/message_driver.rb +0 -1
- data/lib/message_driver/adapters/base.rb +10 -10
- data/lib/message_driver/adapters/bunny_adapter.rb +57 -30
- data/lib/message_driver/adapters/in_memory_adapter.rb +4 -5
- data/lib/message_driver/adapters/stomp_adapter.rb +4 -6
- data/lib/message_driver/broker.rb +5 -4
- data/lib/message_driver/client.rb +6 -6
- data/lib/message_driver/destination.rb +2 -2
- data/lib/message_driver/errors.rb +1 -4
- data/lib/message_driver/logging.rb +1 -1
- data/lib/message_driver/message.rb +2 -2
- data/lib/message_driver/subscription.rb +1 -1
- data/lib/message_driver/version.rb +1 -1
- data/lib/{message_driver/vendor → vendor}/.document +0 -0
- data/lib/vendor/nesty.rb +1 -0
- data/lib/vendor/nesty/nested_error.rb +28 -0
- data/message-driver.gemspec +15 -14
- data/spec/integration/bunny/amqp_integration_spec.rb +43 -43
- data/spec/integration/bunny/bunny_adapter_spec.rb +117 -101
- data/spec/integration/in_memory/in_memory_adapter_spec.rb +35 -35
- data/spec/integration/stomp/stomp_adapter_spec.rb +42 -42
- data/spec/spec_helper.rb +4 -1
- data/spec/support/shared/adapter_examples.rb +7 -7
- data/spec/support/shared/client_ack_examples.rb +6 -6
- data/spec/support/shared/context_examples.rb +4 -4
- data/spec/support/shared/destination_examples.rb +10 -10
- data/spec/support/shared/subscription_examples.rb +29 -29
- data/spec/support/shared/transaction_examples.rb +10 -10
- data/spec/units/message_driver/adapters/base_spec.rb +19 -19
- data/spec/units/message_driver/broker_spec.rb +57 -58
- data/spec/units/message_driver/client_spec.rb +84 -84
- data/spec/units/message_driver/destination_spec.rb +4 -4
- data/spec/units/message_driver/message_spec.rb +19 -19
- data/spec/units/message_driver/subscription_spec.rb +4 -4
- data/test_lib/broker_config.rb +2 -2
- metadata +27 -6
- data/lib/message_driver/vendor/nesty.rb +0 -1
- data/lib/message_driver/vendor/nesty/nested_error.rb +0 -26
@@ -7,22 +7,22 @@ module MessageDriver::Adapters
|
|
7
7
|
|
8
8
|
let(:valid_connection_attrs) { BrokerConfig.config }
|
9
9
|
|
10
|
-
describe
|
10
|
+
describe '#initialize' do
|
11
11
|
let(:connection_attrs) { valid_connection_attrs }
|
12
|
-
let(:broker) { double(
|
12
|
+
let(:broker) { double('broker') }
|
13
13
|
|
14
|
-
context
|
15
|
-
shared_examples
|
16
|
-
it
|
17
|
-
stub_const(
|
14
|
+
context 'differing stomp versions' do
|
15
|
+
shared_examples 'raises a stomp error' do
|
16
|
+
it 'raises an error' do
|
17
|
+
stub_const('Stomp::Version::STRING', version)
|
18
18
|
expect {
|
19
19
|
described_class.new(broker, connection_attrs)
|
20
|
-
}.to raise_error MessageDriver::Error,
|
20
|
+
}.to raise_error MessageDriver::Error, 'stomp 1.3.1 or a later version of the 1.3.x series is required for the stomp adapter'
|
21
21
|
end
|
22
22
|
end
|
23
23
|
shared_examples "doesn't raise a stomp error" do
|
24
24
|
it "doesn't raise an an error" do
|
25
|
-
stub_const(
|
25
|
+
stub_const('Stomp::Version::STRING', version)
|
26
26
|
adapter = nil
|
27
27
|
expect {
|
28
28
|
adapter = described_class.new(broker, connection_attrs)
|
@@ -32,7 +32,7 @@ module MessageDriver::Adapters
|
|
32
32
|
%w(1.1.0 1.2.9 1.3.0 1.4.0).each do |v|
|
33
33
|
context "stomp version #{v}" do
|
34
34
|
let(:version) { v }
|
35
|
-
include_examples
|
35
|
+
include_examples 'raises a stomp error'
|
36
36
|
end
|
37
37
|
end
|
38
38
|
%w(1.3.1 1.3.5).each do |v|
|
@@ -43,35 +43,35 @@ module MessageDriver::Adapters
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
describe
|
47
|
-
let(:connection_attrs) { {hosts: [{host:
|
46
|
+
describe 'the resulting config' do
|
47
|
+
let(:connection_attrs) { {hosts: [{host: 'my_host'}]} }
|
48
48
|
subject(:config) { described_class.new(broker, connection_attrs).config }
|
49
49
|
|
50
|
-
its([:connect_headers]) { should eq(:"accept-version" =>
|
50
|
+
its([:connect_headers]) { should eq(:"accept-version" => '1.1,1.2') }
|
51
51
|
its([:hosts]) { should eq(connection_attrs[:hosts]) }
|
52
52
|
|
53
|
-
context
|
54
|
-
let(:connection_attrs) { {hosts: [{host:
|
53
|
+
context 'when vhost is specified' do
|
54
|
+
let(:connection_attrs) { {hosts: [{host: 'my_host'}], vhost: 'my_vhost'} }
|
55
55
|
|
56
56
|
it { should_not have_key(:vhost) }
|
57
|
-
its([:connect_headers]) { should eq(:"accept-version" =>
|
57
|
+
its([:connect_headers]) { should eq(:"accept-version" => '1.1,1.2', :"host" => 'my_vhost') }
|
58
58
|
end
|
59
59
|
|
60
|
-
context
|
61
|
-
let(:connection_attrs) { {hosts: [{host:
|
60
|
+
context 'when there are things in the connect_headers' do
|
61
|
+
let(:connection_attrs) { {hosts: [{host: 'my_host'}], connect_headers: {'foo' => 'bar'}} }
|
62
62
|
|
63
|
-
its([:connect_headers]) { should eq(:"accept-version" =>
|
63
|
+
its([:connect_headers]) { should eq(:"accept-version" => '1.1,1.2', 'foo' => 'bar') }
|
64
64
|
|
65
|
-
context
|
66
|
-
let(:connection_attrs) { {hosts: [{host:
|
65
|
+
context 'and accept-version is one of the parameters' do
|
66
|
+
let(:connection_attrs) { {hosts: [{host: 'my_host'}], connect_headers: {'foo' => 'bar', :"accept-version" => 'foo!'}} }
|
67
67
|
|
68
|
-
its([:connect_headers]) { should eq(:"accept-version" =>
|
68
|
+
its([:connect_headers]) { should eq(:"accept-version" => '1.1,1.2', 'foo' => 'bar') }
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
shared_context
|
74
|
+
shared_context 'a connected stomp adapter' do
|
75
75
|
let(:broker) { MessageDriver::Broker.configure(valid_connection_attrs) }
|
76
76
|
subject(:adapter) { broker.adapter }
|
77
77
|
|
@@ -80,54 +80,54 @@ module MessageDriver::Adapters
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
it_behaves_like
|
84
|
-
include_context
|
83
|
+
it_behaves_like 'an adapter' do
|
84
|
+
include_context 'a connected stomp adapter'
|
85
85
|
end
|
86
86
|
|
87
|
-
describe
|
88
|
-
include_context
|
87
|
+
describe '#new_context' do
|
88
|
+
include_context 'a connected stomp adapter'
|
89
89
|
|
90
|
-
it
|
90
|
+
it 'returns a StompAdapter::StompContext' do
|
91
91
|
expect(adapter.new_context).to be_a StompAdapter::StompContext
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
95
|
describe StompAdapter::StompContext do
|
96
|
-
include_context
|
96
|
+
include_context 'a connected stomp adapter'
|
97
97
|
subject(:adapter_context) { adapter.new_context }
|
98
98
|
|
99
|
-
it_behaves_like
|
100
|
-
it_behaves_like
|
101
|
-
it_behaves_like
|
102
|
-
it_behaves_like
|
99
|
+
it_behaves_like 'an adapter context'
|
100
|
+
it_behaves_like 'transactions are not supported'
|
101
|
+
it_behaves_like 'client acks are not supported'
|
102
|
+
it_behaves_like 'subscriptions are not supported'
|
103
103
|
|
104
|
-
describe
|
104
|
+
describe '#create_destination' do
|
105
105
|
|
106
|
-
context
|
107
|
-
let(:dest_name) {
|
106
|
+
context 'the resulting destination' do
|
107
|
+
let(:dest_name) { '/queue/stomp_destination_spec' }
|
108
108
|
subject(:destination) { adapter_context.create_destination(dest_name) }
|
109
109
|
|
110
110
|
it { should be_a StompAdapter::Destination }
|
111
111
|
|
112
|
-
it_behaves_like
|
112
|
+
it_behaves_like 'a destination'
|
113
113
|
include_examples "doesn't support #message_count"
|
114
114
|
|
115
|
-
describe
|
116
|
-
context
|
117
|
-
let(:body) {
|
115
|
+
describe 'pop_message' do
|
116
|
+
context 'when there is a message on the queue' do
|
117
|
+
let(:body) { 'Testing stomp pop_message' }
|
118
118
|
before do
|
119
119
|
destination.publish(body)
|
120
120
|
end
|
121
121
|
|
122
|
-
it
|
122
|
+
it 'returns the message' do
|
123
123
|
msg = destination.pop_message
|
124
124
|
expect(msg).to be_a MessageDriver::Adapters::StompAdapter::Message
|
125
125
|
expect(msg.body).to eq(body)
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
context
|
130
|
-
it
|
129
|
+
context 'when the queue is empty' do
|
130
|
+
it 'returns nil' do
|
131
131
|
msg = destination.pop_message
|
132
132
|
expect(msg).to be_nil
|
133
133
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear!
|
3
|
+
|
1
4
|
require 'message_driver'
|
2
5
|
|
3
6
|
require File.join(File.dirname(__FILE__), '..', 'test_lib', 'broker_config')
|
4
7
|
|
5
|
-
Dir[
|
8
|
+
Dir['./spec/support/**/*.rb'].sort.each {|f| require f}
|
6
9
|
|
7
10
|
RSpec.configure do |c|
|
8
11
|
c.treat_symbols_as_metadata_keys_with_true_values = true
|
@@ -1,12 +1,12 @@
|
|
1
|
-
shared_examples
|
2
|
-
describe
|
3
|
-
it
|
1
|
+
shared_examples 'an adapter' do
|
2
|
+
describe '#new_context' do
|
3
|
+
it 'returns a MessageDriver::Adapters::ContextBase' do
|
4
4
|
expect(subject.new_context).to be_a MessageDriver::Adapters::ContextBase
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
-
describe
|
9
|
-
it
|
8
|
+
describe '#stop' do
|
9
|
+
it 'invalidates all the adapter contexts' do
|
10
10
|
ctx1 = subject.new_context
|
11
11
|
ctx2 = subject.new_context
|
12
12
|
subject.stop
|
@@ -15,8 +15,8 @@ shared_examples "an adapter" do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
describe
|
19
|
-
it
|
18
|
+
describe '#broker' do
|
19
|
+
it 'returns the broker associated with the adapter' do
|
20
20
|
expect(subject.broker).to be(broker)
|
21
21
|
end
|
22
22
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
shared_examples
|
2
|
-
describe
|
3
|
-
it
|
1
|
+
shared_examples 'client acks are supported' do
|
2
|
+
describe '#supports_client_acks' do
|
3
|
+
it 'returns true' do
|
4
4
|
expect(subject.supports_client_acks?).to eq(true)
|
5
5
|
end
|
6
6
|
end
|
@@ -9,9 +9,9 @@ shared_examples "client acks are supported" do
|
|
9
9
|
it { should respond_to :nack_message }
|
10
10
|
end
|
11
11
|
|
12
|
-
shared_examples
|
13
|
-
describe
|
14
|
-
it
|
12
|
+
shared_examples 'client acks are not supported' do
|
13
|
+
describe '#supports_client_acks' do
|
14
|
+
it 'returns false' do
|
15
15
|
expect(subject.supports_client_acks?).to eq(false)
|
16
16
|
end
|
17
17
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
shared_examples
|
1
|
+
shared_examples 'an adapter context' do
|
2
2
|
it { should be_a MessageDriver::Adapters::ContextBase }
|
3
3
|
|
4
4
|
its(:adapter) { should be adapter }
|
5
5
|
|
6
|
-
it
|
6
|
+
it 'is initially valid' do
|
7
7
|
should be_valid
|
8
8
|
end
|
9
9
|
|
10
|
-
describe
|
11
|
-
it
|
10
|
+
describe '#invalidate' do
|
11
|
+
it 'causes the context to become invalid' do
|
12
12
|
subject.invalidate
|
13
13
|
expect(subject).to_not be_valid
|
14
14
|
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
shared_examples
|
1
|
+
shared_examples 'a destination' do
|
2
2
|
its(:adapter) { should be adapter }
|
3
3
|
|
4
|
-
describe
|
5
|
-
let(:body) {
|
6
|
-
let(:headers) { {
|
4
|
+
describe '#pop_message' do
|
5
|
+
let(:body) { 'The message body' }
|
6
|
+
let(:headers) { { 'foo' => 'bar', 'bar' => 'baz'} }
|
7
7
|
let(:properties) { {persistent: true, client_ack: true} }
|
8
8
|
|
9
9
|
before do
|
10
10
|
destination.publish(body, headers, properties)
|
11
11
|
end
|
12
12
|
|
13
|
-
context
|
13
|
+
context 'the result' do
|
14
14
|
subject(:message) { destination.pop_message }
|
15
15
|
|
16
16
|
it { should be_a MessageDriver::Message::Base }
|
@@ -22,8 +22,8 @@ shared_examples "a destination" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
shared_examples "doesn't support #message_count" do
|
25
|
-
describe
|
26
|
-
it
|
25
|
+
describe '#message_count' do
|
26
|
+
it 'raises an error' do
|
27
27
|
expect {
|
28
28
|
destination.message_count
|
29
29
|
}.to raise_error "#message_count is not supported by #{destination.class}"
|
@@ -31,11 +31,11 @@ shared_examples "doesn't support #message_count" do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
shared_examples
|
34
|
+
shared_examples 'supports #message_count' do
|
35
35
|
it "reports it's message_count" do
|
36
36
|
expect {
|
37
|
-
destination.publish(
|
38
|
-
destination.publish(
|
37
|
+
destination.publish('msg1')
|
38
|
+
destination.publish('msg2')
|
39
39
|
pause_if_needed
|
40
40
|
}.to change{destination.message_count}.by(2)
|
41
41
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
-
shared_examples
|
2
|
-
describe
|
3
|
-
it
|
1
|
+
shared_examples 'subscriptions are not supported' do
|
2
|
+
describe '#supports_subscriptions?' do
|
3
|
+
it 'returns false' do
|
4
4
|
expect(subject.supports_subscriptions?).to eq(false)
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
8
|
-
describe
|
9
|
-
it
|
10
|
-
destination = double(
|
11
|
-
consumer = lambda do |
|
8
|
+
describe '#subscribe' do
|
9
|
+
it 'raises an error' do
|
10
|
+
destination = double('destination')
|
11
|
+
consumer = lambda do |_| end
|
12
12
|
expect {
|
13
13
|
subject.subscribe(destination, &consumer)
|
14
14
|
}.to raise_error "#subscribe is not supported by #{subject.adapter.class}"
|
@@ -16,17 +16,17 @@ shared_examples "subscriptions are not supported" do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
shared_examples
|
20
|
-
describe
|
21
|
-
it
|
19
|
+
shared_examples 'subscriptions are supported' do |subscription_type|
|
20
|
+
describe '#supports_subscriptions?' do
|
21
|
+
it 'returns true' do
|
22
22
|
expect(subject.supports_subscriptions?).to eq(true)
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
let(:destination) { adapter_context.create_destination(
|
26
|
+
let(:destination) { adapter_context.create_destination('subscriptions_example_queue') }
|
27
27
|
|
28
|
-
let(:message1) {
|
29
|
-
let(:message2) {
|
28
|
+
let(:message1) { 'message 1' }
|
29
|
+
let(:message2) { 'message 2' }
|
30
30
|
let(:messages) { [] }
|
31
31
|
let(:consumer) do
|
32
32
|
lambda do |msg|
|
@@ -34,7 +34,7 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
describe
|
37
|
+
describe '#subscribe' do
|
38
38
|
before do
|
39
39
|
if destination.respond_to? :purge
|
40
40
|
destination.purge
|
@@ -46,11 +46,11 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
46
46
|
subscription.unsubscribe
|
47
47
|
end
|
48
48
|
|
49
|
-
it
|
49
|
+
it 'returns a MessageDriver::Subscription::Base' do
|
50
50
|
expect(subscription).to be_a MessageDriver::Subscription::Base
|
51
51
|
end
|
52
52
|
|
53
|
-
context
|
53
|
+
context 'the subscription' do
|
54
54
|
subject { subscription }
|
55
55
|
|
56
56
|
it { should be_a MessageDriver::Subscription::Base }
|
@@ -59,23 +59,23 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
59
59
|
its(:destination) { should be destination }
|
60
60
|
its(:consumer) { should be consumer }
|
61
61
|
|
62
|
-
describe
|
62
|
+
describe '#unsubscribe' do
|
63
63
|
it "makes it so messages don't go to the consumer any more" do
|
64
64
|
subscription.unsubscribe
|
65
65
|
expect {
|
66
|
-
destination.publish(
|
66
|
+
destination.publish('should not be consumed')
|
67
67
|
}.to_not change{messages.size}
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
context
|
72
|
+
context 'when there are already messages in the destination' do
|
73
73
|
before do
|
74
74
|
destination.publish(message1)
|
75
75
|
destination.publish(message2)
|
76
76
|
end
|
77
77
|
|
78
|
-
it
|
78
|
+
it 'plays the messages into the consumer' do
|
79
79
|
expect {
|
80
80
|
subscription
|
81
81
|
pause_if_needed
|
@@ -85,7 +85,7 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
85
85
|
expect(bodies).to include(message2)
|
86
86
|
end
|
87
87
|
|
88
|
-
it
|
88
|
+
it 'removes the messages from the queue' do
|
89
89
|
pause_if_needed
|
90
90
|
expect {
|
91
91
|
subscription
|
@@ -94,12 +94,12 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
context
|
97
|
+
context 'when a message is published to the destination' do
|
98
98
|
before do
|
99
99
|
subscription
|
100
100
|
end
|
101
101
|
|
102
|
-
it
|
102
|
+
it 'consumers the message into the consumer instead of putting them on the queue' do
|
103
103
|
expect {
|
104
104
|
expect {
|
105
105
|
subject.publish(destination, message1)
|
@@ -110,10 +110,10 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
110
110
|
end
|
111
111
|
end
|
112
112
|
|
113
|
-
context
|
114
|
-
let(:error) { RuntimeError.new(
|
113
|
+
context 'when the consumer raises an error' do
|
114
|
+
let(:error) { RuntimeError.new('oh nos!') }
|
115
115
|
let(:consumer) do
|
116
|
-
lambda do |
|
116
|
+
lambda do |_|
|
117
117
|
raise error
|
118
118
|
end
|
119
119
|
end
|
@@ -123,7 +123,7 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
123
123
|
destination.publish(message2)
|
124
124
|
end
|
125
125
|
|
126
|
-
it
|
126
|
+
it 'keeps processing the messages' do
|
127
127
|
pause_if_needed
|
128
128
|
expect {
|
129
129
|
subscription
|
@@ -131,11 +131,11 @@ shared_examples "subscriptions are supported" do |subscription_type|
|
|
131
131
|
}.to change{destination.message_count}.from(2).to(0)
|
132
132
|
end
|
133
133
|
|
134
|
-
context
|
134
|
+
context 'an error_handler is provided' do
|
135
135
|
let(:error_handler) { double(:error_handler, call: nil) }
|
136
136
|
let(:subscription) { adapter_context.subscribe(destination, error_handler: error_handler, &consumer) }
|
137
137
|
|
138
|
-
it
|
138
|
+
it 'passes the errors and the messages to the error handler' do
|
139
139
|
subscription
|
140
140
|
pause_if_needed
|
141
141
|
expect(error_handler).to have_received(:call).with(error, kind_of(MessageDriver::Message::Base)).at_least(2).times
|