message-driver 0.1.0 → 0.2.0.rc1
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 +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +18 -7
- data/CHANGELOG.md +12 -2
- data/Gemfile +17 -0
- data/Guardfile +8 -4
- data/README.md +14 -5
- data/Rakefile +44 -11
- data/examples/basic_producer_and_consumer/Gemfile +5 -0
- data/examples/basic_producer_and_consumer/common.rb +17 -0
- data/examples/basic_producer_and_consumer/consumer.rb +24 -0
- data/examples/basic_producer_and_consumer/producer.rb +33 -0
- data/features/.nav +8 -0
- data/features/CHANGELOG.md +12 -2
- data/features/amqp_specific_features/binding_amqp_destinations.feature +7 -7
- data/features/amqp_specific_features/declaring_amqp_exchanges.feature +3 -3
- data/features/amqp_specific_features/nack_redelivered_messages.feature +92 -0
- data/features/amqp_specific_features/requeueing_on_nack.feature +44 -0
- data/features/amqp_specific_features/server_named_destinations.feature +5 -5
- data/features/client_acks.feature +92 -0
- data/features/destination_metadata.feature +9 -11
- data/features/dynamic_destinations.feature +7 -7
- data/features/error_handling.feature +11 -9
- data/features/logging.feature +14 -0
- data/features/message_consumers/auto_ack_consumers.feature +79 -0
- data/features/message_consumers/manual_ack_consumers.feature +95 -0
- data/features/message_consumers/transactional_ack_consumers.feature +77 -0
- data/features/message_consumers.feature +54 -0
- data/features/publishing_a_message.feature +6 -10
- data/features/publishing_with_transactions.feature +10 -14
- data/features/rabbitmq_specific_features/dead_letter_queueing.feature +116 -0
- data/features/step_definitions/dynamic_destinations_steps.rb +3 -3
- data/features/step_definitions/error_handling_steps.rb +4 -2
- data/features/step_definitions/logging_steps.rb +28 -0
- data/features/step_definitions/message_consumers_steps.rb +29 -0
- data/features/step_definitions/steps.rb +60 -9
- data/features/support/broker_config_helper.rb +19 -0
- data/features/support/env.rb +1 -0
- data/features/support/firewall_helper.rb +8 -11
- data/features/support/message_table_matcher.rb +21 -5
- data/features/support/test_runner.rb +39 -16
- data/lib/message_driver/adapters/base.rb +51 -4
- data/lib/message_driver/adapters/bunny_adapter.rb +251 -127
- data/lib/message_driver/adapters/in_memory_adapter.rb +97 -18
- data/lib/message_driver/adapters/stomp_adapter.rb +127 -0
- data/lib/message_driver/broker.rb +23 -24
- data/lib/message_driver/client.rb +157 -0
- data/lib/message_driver/destination.rb +7 -4
- data/lib/message_driver/errors.rb +27 -0
- data/lib/message_driver/logging.rb +11 -0
- data/lib/message_driver/message.rb +8 -0
- data/lib/message_driver/subscription.rb +18 -0
- data/lib/message_driver/vendor/.document +0 -0
- data/lib/message_driver/vendor/nesty/nested_error.rb +26 -0
- data/lib/message_driver/vendor/nesty.rb +1 -0
- data/lib/message_driver/version.rb +1 -1
- data/lib/message_driver.rb +4 -2
- data/message-driver.gemspec +4 -4
- data/spec/integration/{amqp_integration_spec.rb → bunny/amqp_integration_spec.rb} +29 -28
- data/spec/integration/bunny/bunny_adapter_spec.rb +339 -0
- data/spec/integration/in_memory/in_memory_adapter_spec.rb +126 -0
- data/spec/integration/stomp/stomp_adapter_spec.rb +142 -0
- data/spec/spec_helper.rb +5 -2
- data/spec/support/shared/adapter_examples.rb +17 -0
- data/spec/support/shared/client_ack_examples.rb +18 -0
- data/spec/support/shared/context_examples.rb +14 -0
- data/spec/support/shared/destination_examples.rb +4 -5
- data/spec/support/shared/subscription_examples.rb +146 -0
- data/spec/support/shared/transaction_examples.rb +43 -0
- data/spec/support/utils.rb +14 -0
- data/spec/units/message_driver/adapters/base_spec.rb +38 -19
- data/spec/units/message_driver/broker_spec.rb +71 -18
- data/spec/units/message_driver/client_spec.rb +375 -0
- data/spec/units/message_driver/destination_spec.rb +9 -0
- data/spec/units/message_driver/logging_spec.rb +18 -0
- data/spec/units/message_driver/message_spec.rb +36 -0
- data/spec/units/message_driver/subscription_spec.rb +24 -0
- data/test_lib/broker_config.rb +50 -20
- metadata +83 -45
- data/.rbenv-version +0 -1
- data/lib/message_driver/exceptions.rb +0 -18
- data/lib/message_driver/message_publisher.rb +0 -15
- data/spec/integration/message_driver/adapters/bunny_adapter_spec.rb +0 -301
- data/spec/units/message_driver/adapters/in_memory_adapter_spec.rb +0 -43
- data/spec/units/message_driver/message_publisher_spec.rb +0 -65
@@ -0,0 +1,116 @@
|
|
1
|
+
@bunny
|
2
|
+
Feature: DLQ-ing messages with nacks and consumers
|
3
|
+
|
4
|
+
RabbitMQ supports sending messages to a DLQ if configured correctly.
|
5
|
+
See http://www.rabbitmq.com/dlx.html for details.
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given the following broker configuration
|
9
|
+
"""ruby
|
10
|
+
MessageDriver::Broker.define do |b|
|
11
|
+
# declare a dead letter exchange
|
12
|
+
b.destination :rabbit_dlx, "rabbit.dead.letter.exchange", type: :exchange, declare: { type: :fanout }
|
13
|
+
|
14
|
+
# declare a dead letter queue and bind it to the exchange
|
15
|
+
b.destination :rabbit_dlq, "rabbit.dead.letter.queue", bindings: [
|
16
|
+
{ source: "rabbit.dead.letter.exchange" }
|
17
|
+
]
|
18
|
+
|
19
|
+
# declare a work queue that sends dead letters to our dead letter queue
|
20
|
+
b.destination :rabbit_work, "rabbit.work", arguments: { :"x-dead-letter-exchange" => "rabbit.dead.letter.exchange" }
|
21
|
+
end
|
22
|
+
"""
|
23
|
+
And I have no messages on :rabbit_work
|
24
|
+
And I have no messages on :rabbit_dlq
|
25
|
+
|
26
|
+
Scenario: Nacking a message with requeue false
|
27
|
+
Given I send the following message to :rabbit_work
|
28
|
+
| body |
|
29
|
+
| Nack Test 1 |
|
30
|
+
|
31
|
+
When I execute the following code
|
32
|
+
"""ruby
|
33
|
+
message = MessageDriver::Client.pop_message(:rabbit_work, client_ack: true)
|
34
|
+
message.nack(requeue: false)
|
35
|
+
"""
|
36
|
+
|
37
|
+
Then I expect to find no messages on :rabbit_work
|
38
|
+
And I expect to find the following 1 message on :rabbit_dlq
|
39
|
+
| body |
|
40
|
+
| Nack Test 1 |
|
41
|
+
|
42
|
+
|
43
|
+
Scenario: Nacking a message on a manual_ack consumer
|
44
|
+
Given I have a message consumer
|
45
|
+
"""ruby
|
46
|
+
MessageDriver::Broker.consumer(:manual_dql) do |message|
|
47
|
+
message.nack(requeue: false)
|
48
|
+
end
|
49
|
+
"""
|
50
|
+
And I create a subscription
|
51
|
+
"""ruby
|
52
|
+
MessageDriver::Client.subscribe(:rabbit_work, :manual_dql, ack: :manual)
|
53
|
+
"""
|
54
|
+
|
55
|
+
When I send the following messages to :rabbit_work
|
56
|
+
| body |
|
57
|
+
| Manual Nack 1 |
|
58
|
+
| Manual Nack 2 |
|
59
|
+
And I let the subscription process
|
60
|
+
|
61
|
+
Then I expect to find no messages on :rabbit_work
|
62
|
+
And I expect to find the following 2 messages on :rabbit_dlq
|
63
|
+
| body |
|
64
|
+
| Manual Nack 1 |
|
65
|
+
| Manual Nack 2 |
|
66
|
+
|
67
|
+
|
68
|
+
Scenario: Raising a DontRequeueError in an auto_ack consumer
|
69
|
+
Given I have a message consumer
|
70
|
+
"""ruby
|
71
|
+
MessageDriver::Broker.consumer(:manual_dql) do |message|
|
72
|
+
raise MessageDriver::DontRequeueError
|
73
|
+
end
|
74
|
+
"""
|
75
|
+
And I create a subscription
|
76
|
+
"""ruby
|
77
|
+
MessageDriver::Client.subscribe(:rabbit_work, :manual_dql, ack: :auto)
|
78
|
+
"""
|
79
|
+
|
80
|
+
When I send the following messages to :rabbit_work
|
81
|
+
| body |
|
82
|
+
| Auto Nack 1 |
|
83
|
+
| Auto Nack 2 |
|
84
|
+
And I let the subscription process
|
85
|
+
|
86
|
+
Then I expect to find no messages on :rabbit_work
|
87
|
+
And I expect to find the following 2 messages on :rabbit_dlq
|
88
|
+
| body |
|
89
|
+
| Auto Nack 1 |
|
90
|
+
| Auto Nack 2 |
|
91
|
+
|
92
|
+
|
93
|
+
Scenario: Raising a DontRequeueError in a transactional consumer
|
94
|
+
Given I have a message consumer
|
95
|
+
"""ruby
|
96
|
+
MessageDriver::Broker.consumer(:transactional_dql) do |message|
|
97
|
+
publish(:rabbit_work, "I get rolled back")
|
98
|
+
raise MessageDriver::DontRequeueError
|
99
|
+
end
|
100
|
+
"""
|
101
|
+
And I create a subscription
|
102
|
+
"""ruby
|
103
|
+
MessageDriver::Client.subscribe(:rabbit_work, :transactional_dql, ack: :transactional)
|
104
|
+
"""
|
105
|
+
|
106
|
+
When I send the following messages to :rabbit_work
|
107
|
+
| body |
|
108
|
+
| Transactional Nack 1 |
|
109
|
+
| Transactional Nack 2 |
|
110
|
+
And I let the subscription process
|
111
|
+
|
112
|
+
Then I expect to find no messages on :rabbit_work
|
113
|
+
And I expect to find the following 2 messages on :rabbit_dlq
|
114
|
+
| body |
|
115
|
+
| Transactional Nack 1 |
|
116
|
+
| Transactional Nack 2 |
|
@@ -1,9 +1,9 @@
|
|
1
|
-
Given(/^I have a dynamic destination "(#{STRING_OR_SYM})" with the following messages on it
|
2
|
-
dest = MessageDriver::Broker.dynamic_destination(destination
|
1
|
+
Given(/^I have a dynamic destination "(#{STRING_OR_SYM})" with the following messages on it$/) do |destination, table|
|
2
|
+
dest = MessageDriver::Broker.dynamic_destination(destination)
|
3
3
|
test_runner.publish_table_to_destination(dest, table)
|
4
4
|
end
|
5
5
|
|
6
|
-
Then(/^I expect to find (#{NUMBER}) messages? on the dynamic destination "(#{STRING_OR_SYM})" with
|
6
|
+
Then(/^I expect to find (#{NUMBER}) messages? on the dynamic destination "(#{STRING_OR_SYM})" with$/) do |count, destination, table|
|
7
7
|
expect(test_runner).to have_no_errors
|
8
8
|
dest = MessageDriver::Broker.dynamic_destination(destination, passive: true)
|
9
9
|
messages = test_runner.fetch_messages(dest)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
LOG_FILE_NAME = "cucumber_log_file.log"
|
4
|
+
|
5
|
+
Given(/^I am logging to a log file(?: at the (#{STRING_OR_SYM}) level)?$/) do |level|
|
6
|
+
step "an empty file named \"#{LOG_FILE_NAME}\""
|
7
|
+
in_current_dir do
|
8
|
+
@logger = Logger.new(LOG_FILE_NAME)
|
9
|
+
end
|
10
|
+
step "I set the log level to #{level || "info"}"
|
11
|
+
scenario_config[:logger] = @logger
|
12
|
+
end
|
13
|
+
|
14
|
+
Given(/^I set the log level to (#{STRING_OR_SYM})$/) do |level|
|
15
|
+
level = level ? level.to_s.upcase : "INFO"
|
16
|
+
@logger.level = Logger::SEV_LABEL.find_index(level)
|
17
|
+
end
|
18
|
+
|
19
|
+
Then "the log file should contain:" do |string|
|
20
|
+
step "the file \"#{LOG_FILE_NAME}\" should contain:", string
|
21
|
+
end
|
22
|
+
|
23
|
+
After do
|
24
|
+
if @logger
|
25
|
+
@logger.close
|
26
|
+
@logger = nil
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
Given "I have a message consumer" do |src|
|
2
|
+
test_runner.run_config_code(src)
|
3
|
+
expect(test_runner).to have_no_errors
|
4
|
+
end
|
5
|
+
|
6
|
+
Given(/^I subscribe to (#{STRING_OR_SYM}) with (#{STRING_OR_SYM})$/) do |destination, consumer|
|
7
|
+
MessageDriver::Client.subscribe(destination, consumer)
|
8
|
+
end
|
9
|
+
|
10
|
+
Given "I create a subscription" do |src|
|
11
|
+
test_runner.run_test_code("@subscription = #{src}")
|
12
|
+
expect(test_runner).to have_no_errors
|
13
|
+
end
|
14
|
+
|
15
|
+
When "I cancel the subscription" do
|
16
|
+
test_runner.run_test_code("@subscription.unsubscribe")
|
17
|
+
step "I allow for processing"
|
18
|
+
end
|
19
|
+
|
20
|
+
When "I let the subscription process" do
|
21
|
+
step "I allow for processing"
|
22
|
+
step "I cancel the subscription"
|
23
|
+
expect(test_runner).to have_no_errors
|
24
|
+
end
|
25
|
+
|
26
|
+
When "I restart the subscription" do
|
27
|
+
test_runner.run_test_code("@subscription.start")
|
28
|
+
step "I allow for processing"
|
29
|
+
end
|
@@ -1,27 +1,68 @@
|
|
1
1
|
Given "I am connected to the broker" do
|
2
|
-
MessageDriver.configure(
|
2
|
+
MessageDriver.configure(broker_config)
|
3
3
|
end
|
4
4
|
|
5
|
-
Given "the following broker configuration
|
5
|
+
Given "the following broker configuration" do |src|
|
6
6
|
step "I am connected to the broker"
|
7
|
-
test_runner.
|
7
|
+
test_runner.run_config_code(src)
|
8
8
|
end
|
9
9
|
|
10
|
-
|
10
|
+
Given(/^I have a destination (#{STRING_OR_SYM})$/) do |destination|
|
11
|
+
MessageDriver::Broker.define do |b|
|
12
|
+
b.destination(destination, destination.to_s)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Given(/^I have a destination (#{STRING_OR_SYM}) with no messages on it$/) do |destination|
|
17
|
+
dest = destination.kind_of?(Symbol) ? destination.inspect : destination.to_s
|
18
|
+
step "I have a destination #{dest}"
|
19
|
+
test_runner.purge_destination(destination)
|
20
|
+
end
|
21
|
+
|
22
|
+
Given(/^I have the following messages? on (#{STRING_OR_SYM})$/) do |destination, table|
|
23
|
+
test_runner.purge_destination(destination)
|
24
|
+
dest = destination.kind_of?(Symbol) ? destination.inspect : destination.to_s
|
25
|
+
step "I send the following messages to #{dest}", table
|
26
|
+
end
|
27
|
+
|
28
|
+
Given(/^I have no messages on (#{STRING_OR_SYM})$/) do |destination|
|
29
|
+
test_runner.purge_destination(destination)
|
30
|
+
end
|
31
|
+
|
32
|
+
When(/^I send the following messages? to (#{STRING_OR_SYM})$/) do |destination, table|
|
33
|
+
table.hashes.each do |msg|
|
34
|
+
MessageDriver::Client.publish(destination, msg[:body])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
When "I execute the following code" do |src|
|
11
39
|
test_runner.run_test_code(src)
|
12
40
|
end
|
13
41
|
|
42
|
+
When "I reset the context" do
|
43
|
+
MessageDriver::Client.current_adapter_context.invalidate
|
44
|
+
end
|
45
|
+
|
46
|
+
When "I allow for processing" do
|
47
|
+
test_runner.pause_if_needed
|
48
|
+
end
|
49
|
+
|
14
50
|
Then(/^I expect to find (#{NUMBER}) messages? on (#{STRING_OR_SYM})$/) do |count, destination|
|
15
51
|
expect(test_runner).to have_no_errors
|
16
52
|
messages = test_runner.fetch_messages(destination)
|
17
|
-
expect(messages).to have(count).items
|
53
|
+
expect(messages).to have(count).items, "expected #{count} messages, but got these instead: #{messages.map(&:body)}"
|
18
54
|
end
|
19
55
|
|
20
|
-
Then(/^I expect to find (#{NUMBER}) messages? on (#{STRING_OR_SYM})
|
56
|
+
Then(/^I expect to find the following (#{NUMBER}) messages? on (#{STRING_OR_SYM})$/) do |count, destination, table|
|
21
57
|
expect(test_runner).to have_no_errors
|
22
58
|
messages = test_runner.fetch_messages(destination)
|
23
|
-
expect(messages).to have(count).items
|
24
59
|
expect(messages).to match_message_table(table)
|
60
|
+
expect(messages).to have(count).items
|
61
|
+
end
|
62
|
+
|
63
|
+
Then(/^I expect to find the following message on (#{STRING_OR_SYM})$/) do |destination, table|
|
64
|
+
dest = destination.kind_of?(Symbol) ? destination.inspect : destination.to_s
|
65
|
+
step "I expect to find the following 1 message on #{dest}", table
|
25
66
|
end
|
26
67
|
|
27
68
|
Then(/^I expect it to raise "(.*?)"$/) do |error_msg|
|
@@ -31,11 +72,21 @@ Then(/^I expect it to raise "(.*?)"$/) do |error_msg|
|
|
31
72
|
end
|
32
73
|
|
33
74
|
Then(/^I expect it to raise a (.*?) error$/) do |error_type|
|
34
|
-
|
35
|
-
expect(
|
75
|
+
err = test_runner.raised_error
|
76
|
+
expect(err).to_not be_nil
|
77
|
+
expect(err.class.to_s).to match error_type
|
36
78
|
test_runner.raised_error = nil
|
37
79
|
end
|
38
80
|
|
39
81
|
Then "I expect to have no errors" do
|
40
82
|
expect(test_runner).to have_no_errors
|
41
83
|
end
|
84
|
+
|
85
|
+
Then "I expect the following check to pass" do |src|
|
86
|
+
step "I execute the following code", src
|
87
|
+
step "I expect to have no errors"
|
88
|
+
end
|
89
|
+
|
90
|
+
Before do |current_scenario|
|
91
|
+
test_runner.current_feature_file = current_scenario.feature.file
|
92
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BrokerConfigHelper
|
2
|
+
def broker_config
|
3
|
+
BrokerConfig.config.merge(@config)
|
4
|
+
end
|
5
|
+
|
6
|
+
def reset_broker_config
|
7
|
+
@config = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def scenario_config
|
11
|
+
@config
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Before do
|
16
|
+
reset_broker_config
|
17
|
+
end
|
18
|
+
|
19
|
+
World(BrokerConfigHelper)
|
data/features/support/env.rb
CHANGED
@@ -1,27 +1,24 @@
|
|
1
1
|
module FirewallHelper
|
2
2
|
|
3
|
+
def self.port
|
4
|
+
BrokerConfig.current_adapter_port
|
5
|
+
end
|
6
|
+
|
3
7
|
COMMANDS = {
|
4
8
|
darwin: {
|
5
9
|
setup: [
|
6
|
-
"
|
10
|
+
"lunchy stop rabbit"
|
7
11
|
],
|
8
12
|
teardown: [
|
9
|
-
"
|
13
|
+
"lunchy start rabbit"
|
10
14
|
]
|
11
15
|
},
|
12
16
|
linux: {
|
13
17
|
setup: [
|
14
|
-
"sudo
|
15
|
-
"sudo iptables -A block-rabbit -p tcp --dport 5672 -j DROP",
|
16
|
-
"sudo iptables -A block-rabbit -p tcp --sport 5672 -j DROP",
|
17
|
-
"sudo iptables -I INPUT -j block-rabbit",
|
18
|
-
"sudo iptables -I OUTPUT -j block-rabbit"
|
18
|
+
"sudo service rabbitmq-server stop"
|
19
19
|
],
|
20
20
|
teardown: [
|
21
|
-
"sudo
|
22
|
-
"sudo iptables -D OUTPUT -j block-rabbit",
|
23
|
-
"sudo iptables -F block-rabbit",
|
24
|
-
"sudo iptables -X block-rabbit"
|
21
|
+
"sudo service rabbitmq-server start"
|
25
22
|
]
|
26
23
|
}
|
27
24
|
}
|
@@ -1,11 +1,27 @@
|
|
1
|
-
RSpec::Matchers.define :match_message_table do |
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
RSpec::Matchers.define :match_message_table do |expected_tbl|
|
2
|
+
define_method :expected_hash do
|
3
|
+
@expected_hash ||= expected_tbl.hashes
|
4
|
+
end
|
5
|
+
|
6
|
+
define_method :messages_to_hash do |messages|
|
7
|
+
messages.collect do |msg|
|
8
|
+
expected_tbl.headers.inject({ }) do |memo, obj|
|
5
9
|
memo[obj] = msg.send(obj)
|
6
10
|
memo
|
7
11
|
end
|
8
12
|
end
|
9
|
-
|
13
|
+
end
|
14
|
+
|
15
|
+
match do |messages|
|
16
|
+
@actual = messages_to_hash(messages)
|
17
|
+
@actual == expected_hash
|
18
|
+
end
|
19
|
+
|
20
|
+
failure_message_for_should do |_|
|
21
|
+
"expected #{expected_hash} and got #{@actual}"
|
22
|
+
end
|
23
|
+
|
24
|
+
description do
|
25
|
+
"contain messages #{expected_hash}"
|
10
26
|
end
|
11
27
|
end
|
@@ -1,36 +1,50 @@
|
|
1
|
-
require 'message_driver'
|
2
|
-
|
3
1
|
class TestRunner
|
4
|
-
include MessageDriver::
|
2
|
+
include MessageDriver::Client
|
5
3
|
include RSpec::Matchers
|
6
4
|
|
7
5
|
attr_accessor :raised_error
|
6
|
+
attr_accessor :current_feature_file
|
8
7
|
|
9
|
-
def
|
10
|
-
instance_eval(src)
|
8
|
+
def run_config_code(src)
|
9
|
+
instance_eval(src, current_feature_file)
|
11
10
|
end
|
12
11
|
|
13
12
|
def run_test_code(src)
|
14
13
|
begin
|
15
|
-
instance_eval(src)
|
16
|
-
rescue
|
14
|
+
instance_eval(src, current_feature_file)
|
15
|
+
rescue => e
|
17
16
|
@raised_error = e
|
18
17
|
end
|
19
18
|
end
|
20
19
|
|
21
|
-
def fetch_messages(
|
20
|
+
def fetch_messages(destination_name)
|
21
|
+
destination = fetch_destination(destination_name)
|
22
|
+
pause_if_needed
|
23
|
+
result = []
|
24
|
+
begin
|
25
|
+
msg = destination.pop_message
|
26
|
+
result << msg unless msg.nil?
|
27
|
+
end until msg.nil?
|
28
|
+
result
|
29
|
+
end
|
30
|
+
|
31
|
+
def purge_destination(destination_name)
|
32
|
+
destination = fetch_destination(destination_name)
|
33
|
+
if destination.respond_to? :purge
|
34
|
+
destination.purge
|
35
|
+
else
|
36
|
+
fetch_messages(destination)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def fetch_destination(destination)
|
22
41
|
case destination
|
23
42
|
when String, Symbol
|
24
|
-
|
43
|
+
MessageDriver::Broker.find_destination(destination)
|
25
44
|
when MessageDriver::Destination::Base
|
26
|
-
|
27
|
-
begin
|
28
|
-
msg = destination.pop_message
|
29
|
-
result << msg unless msg.nil?
|
30
|
-
end until msg.nil?
|
31
|
-
result
|
45
|
+
destination
|
32
46
|
else
|
33
|
-
raise "didn't understand destination #{destination}"
|
47
|
+
raise "didn't understand destination #{destination.inspect}"
|
34
48
|
end
|
35
49
|
end
|
36
50
|
|
@@ -39,6 +53,15 @@ class TestRunner
|
|
39
53
|
destination.publish(msg[:body], msg[:headers]||{}, msg[:properties]||{})
|
40
54
|
end
|
41
55
|
end
|
56
|
+
|
57
|
+
def pause_if_needed(seconds=0.1)
|
58
|
+
seconds *= 10 if ENV['CI'] == 'true'
|
59
|
+
case BrokerConfig.current_adapter
|
60
|
+
when :in_memory
|
61
|
+
else
|
62
|
+
sleep seconds
|
63
|
+
end
|
64
|
+
end
|
42
65
|
end
|
43
66
|
|
44
67
|
module KnowsMyTestRunner
|
@@ -1,10 +1,41 @@
|
|
1
1
|
module MessageDriver
|
2
2
|
module Adapters
|
3
3
|
class Base
|
4
|
+
include Logging
|
5
|
+
|
6
|
+
attr_accessor :contexts
|
7
|
+
|
4
8
|
def initialize(configuration)
|
5
9
|
raise "Must be implemented in subclass"
|
6
10
|
end
|
7
11
|
|
12
|
+
def new_context
|
13
|
+
@contexts ||= []
|
14
|
+
ctx = build_context
|
15
|
+
contexts << ctx
|
16
|
+
ctx
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_context
|
20
|
+
raise "Must be implemented in subclass"
|
21
|
+
end
|
22
|
+
|
23
|
+
def stop
|
24
|
+
contexts.each { |ctx| ctx.invalidate } if contexts
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class ContextBase
|
29
|
+
include Logging
|
30
|
+
|
31
|
+
attr_reader :adapter
|
32
|
+
attr_accessor :valid
|
33
|
+
|
34
|
+
def initialize(adapter)
|
35
|
+
@adapter = adapter
|
36
|
+
@valid = true
|
37
|
+
end
|
38
|
+
|
8
39
|
def publish(destination, body, headers={}, properties={})
|
9
40
|
raise "Must be implemented in subclass"
|
10
41
|
end
|
@@ -13,16 +44,32 @@ module MessageDriver
|
|
13
44
|
raise "Must be implemented in subclass"
|
14
45
|
end
|
15
46
|
|
16
|
-
def
|
17
|
-
raise "
|
47
|
+
def subscribe(destination, options={}, &consumer)
|
48
|
+
raise "#subscribe is not supported by #{adapter.class}"
|
18
49
|
end
|
19
50
|
|
20
51
|
def create_destination(name, dest_options={}, message_props={})
|
21
52
|
raise "Must be implemented in subclass"
|
22
53
|
end
|
23
54
|
|
24
|
-
def
|
25
|
-
|
55
|
+
def valid?
|
56
|
+
@valid
|
57
|
+
end
|
58
|
+
|
59
|
+
def invalidate
|
60
|
+
@valid = false
|
61
|
+
end
|
62
|
+
|
63
|
+
def supports_transactions?
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def supports_client_acks?
|
68
|
+
false
|
69
|
+
end
|
70
|
+
|
71
|
+
def supports_subscriptions?
|
72
|
+
false
|
26
73
|
end
|
27
74
|
end
|
28
75
|
end
|