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.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +18 -7
  4. data/CHANGELOG.md +12 -2
  5. data/Gemfile +17 -0
  6. data/Guardfile +8 -4
  7. data/README.md +14 -5
  8. data/Rakefile +44 -11
  9. data/examples/basic_producer_and_consumer/Gemfile +5 -0
  10. data/examples/basic_producer_and_consumer/common.rb +17 -0
  11. data/examples/basic_producer_and_consumer/consumer.rb +24 -0
  12. data/examples/basic_producer_and_consumer/producer.rb +33 -0
  13. data/features/.nav +8 -0
  14. data/features/CHANGELOG.md +12 -2
  15. data/features/amqp_specific_features/binding_amqp_destinations.feature +7 -7
  16. data/features/amqp_specific_features/declaring_amqp_exchanges.feature +3 -3
  17. data/features/amqp_specific_features/nack_redelivered_messages.feature +92 -0
  18. data/features/amqp_specific_features/requeueing_on_nack.feature +44 -0
  19. data/features/amqp_specific_features/server_named_destinations.feature +5 -5
  20. data/features/client_acks.feature +92 -0
  21. data/features/destination_metadata.feature +9 -11
  22. data/features/dynamic_destinations.feature +7 -7
  23. data/features/error_handling.feature +11 -9
  24. data/features/logging.feature +14 -0
  25. data/features/message_consumers/auto_ack_consumers.feature +79 -0
  26. data/features/message_consumers/manual_ack_consumers.feature +95 -0
  27. data/features/message_consumers/transactional_ack_consumers.feature +77 -0
  28. data/features/message_consumers.feature +54 -0
  29. data/features/publishing_a_message.feature +6 -10
  30. data/features/publishing_with_transactions.feature +10 -14
  31. data/features/rabbitmq_specific_features/dead_letter_queueing.feature +116 -0
  32. data/features/step_definitions/dynamic_destinations_steps.rb +3 -3
  33. data/features/step_definitions/error_handling_steps.rb +4 -2
  34. data/features/step_definitions/logging_steps.rb +28 -0
  35. data/features/step_definitions/message_consumers_steps.rb +29 -0
  36. data/features/step_definitions/steps.rb +60 -9
  37. data/features/support/broker_config_helper.rb +19 -0
  38. data/features/support/env.rb +1 -0
  39. data/features/support/firewall_helper.rb +8 -11
  40. data/features/support/message_table_matcher.rb +21 -5
  41. data/features/support/test_runner.rb +39 -16
  42. data/lib/message_driver/adapters/base.rb +51 -4
  43. data/lib/message_driver/adapters/bunny_adapter.rb +251 -127
  44. data/lib/message_driver/adapters/in_memory_adapter.rb +97 -18
  45. data/lib/message_driver/adapters/stomp_adapter.rb +127 -0
  46. data/lib/message_driver/broker.rb +23 -24
  47. data/lib/message_driver/client.rb +157 -0
  48. data/lib/message_driver/destination.rb +7 -4
  49. data/lib/message_driver/errors.rb +27 -0
  50. data/lib/message_driver/logging.rb +11 -0
  51. data/lib/message_driver/message.rb +8 -0
  52. data/lib/message_driver/subscription.rb +18 -0
  53. data/lib/message_driver/vendor/.document +0 -0
  54. data/lib/message_driver/vendor/nesty/nested_error.rb +26 -0
  55. data/lib/message_driver/vendor/nesty.rb +1 -0
  56. data/lib/message_driver/version.rb +1 -1
  57. data/lib/message_driver.rb +4 -2
  58. data/message-driver.gemspec +4 -4
  59. data/spec/integration/{amqp_integration_spec.rb → bunny/amqp_integration_spec.rb} +29 -28
  60. data/spec/integration/bunny/bunny_adapter_spec.rb +339 -0
  61. data/spec/integration/in_memory/in_memory_adapter_spec.rb +126 -0
  62. data/spec/integration/stomp/stomp_adapter_spec.rb +142 -0
  63. data/spec/spec_helper.rb +5 -2
  64. data/spec/support/shared/adapter_examples.rb +17 -0
  65. data/spec/support/shared/client_ack_examples.rb +18 -0
  66. data/spec/support/shared/context_examples.rb +14 -0
  67. data/spec/support/shared/destination_examples.rb +4 -5
  68. data/spec/support/shared/subscription_examples.rb +146 -0
  69. data/spec/support/shared/transaction_examples.rb +43 -0
  70. data/spec/support/utils.rb +14 -0
  71. data/spec/units/message_driver/adapters/base_spec.rb +38 -19
  72. data/spec/units/message_driver/broker_spec.rb +71 -18
  73. data/spec/units/message_driver/client_spec.rb +375 -0
  74. data/spec/units/message_driver/destination_spec.rb +9 -0
  75. data/spec/units/message_driver/logging_spec.rb +18 -0
  76. data/spec/units/message_driver/message_spec.rb +36 -0
  77. data/spec/units/message_driver/subscription_spec.rb +24 -0
  78. data/test_lib/broker_config.rb +50 -20
  79. metadata +83 -45
  80. data/.rbenv-version +0 -1
  81. data/lib/message_driver/exceptions.rb +0 -18
  82. data/lib/message_driver/message_publisher.rb +0 -15
  83. data/spec/integration/message_driver/adapters/bunny_adapter_spec.rb +0 -301
  84. data/spec/units/message_driver/adapters/in_memory_adapter_spec.rb +0 -43
  85. data/spec/units/message_driver/message_publisher_spec.rb +0 -65
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee1e524ed1e97823d1bf57bebb54afdd7be3d377
4
+ data.tar.gz: a1e55de021a74bcbf71b4df3be92e3f28506464f
5
+ SHA512:
6
+ metadata.gz: aaa3bd79fe84ddb7020fbb1173824d4bd24dba54b86737712bf412f450d07bee650ea1636d411f55a7d19668a950e87d4a583ac28fd2f167814fad1ea253accb
7
+ data.tar.gz: b71dbc3eb07d9f75b00032ea1c8bdcf8412026cc8b51a77c257ec62b8b578d754efdbeaf7a2b5b3a46763f2723150bfd181d970756b3d7852cf01a254a205d4e
data/.gitignore CHANGED
@@ -5,6 +5,7 @@
5
5
  .yardoc
6
6
  .rvmrc
7
7
  .ruby-version
8
+ .rbenv-version
8
9
  Gemfile.lock
9
10
  InstalledFiles
10
11
  _yardoc
data/.travis.yml CHANGED
@@ -5,19 +5,30 @@ services:
5
5
  before_script:
6
6
  - sudo rabbitmqctl add_vhost message-driver-test
7
7
  - sudo rabbitmqctl set_permissions -p message-driver-test guest ".*" ".*" ".*"
8
+ - sudo rabbitmq-plugins enable rabbitmq_stomp
9
+ - sudo service rabbitmq-server restart
10
+ env:
11
+ - ADAPTER=in_memory
12
+ - ADAPTER=bunny:0.9.0
13
+ - ADAPTER=bunny:0.10.0
14
+ - ADAPTER=stomp
15
+ - ADAPTER=bunny:1.0.0.pre
8
16
  rvm:
9
- - 1.9.2
10
- - 1.9.3
11
17
  - 2.0.0
18
+ - 1.9.3
19
+ - 1.9.2
12
20
  - jruby-19mode
13
- - ruby-head
14
21
  - jruby-head
15
22
  - rbx-19mode
16
- env:
17
- - ADAPTER=in_memory
18
- - ADAPTER=bunny
19
23
  matrix:
24
+ exclude:
25
+ - rvm: jruby-19mode
26
+ env: ADAPTER=bunny:0.9.0
27
+ - rvm: jruby-head
28
+ env: ADAPTER=bunny:0.9.0
20
29
  allow_failures:
21
- - rvm: ruby-head
30
+ - env: ADAPTER=bunny:1.0.0.pre
22
31
  - rvm: jruby-head
23
32
  - rvm: rbx-19mode
33
+ - rvm: jruby-19mode
34
+ env: ADAPTER=stomp
data/CHANGELOG.md CHANGED
@@ -1,6 +1,16 @@
1
- # Change Log
1
+ # Changelog
2
2
 
3
- ## 0.1.0
3
+ ## 0.2.0.rc1 - 2013-09-23
4
+
5
+ * Features
6
+ * Message Consumers
7
+ * Bunny and InMemory adapters
8
+ * Client Acks
9
+ * Bunny adapter
10
+ * Adapters
11
+ * begin work on Stomp 1.1/1.2 adapter
12
+
13
+ ## 0.1.0 - 2013-04-05
4
14
 
5
15
  Initial Release
6
16
 
data/Gemfile CHANGED
@@ -16,5 +16,22 @@ group :tools do
16
16
  gem 'ruby_gntp'
17
17
  gem 'rb-fsevent'
18
18
  gem 'relish'
19
+ gem 'lunchy'
20
+ end
21
+ end
22
+
23
+ require File.expand_path("../test_lib/broker_config", __FILE__)
24
+
25
+ adapter = BrokerConfig.current_adapter.to_s
26
+ version = BrokerConfig.adapter_version
27
+
28
+ case adapter
29
+ when 'in_memory'
30
+ else
31
+ case version
32
+ when nil
33
+ gem adapter
34
+ else
35
+ gem adapter.to_s, "~> #{version}"
19
36
  end
20
37
  end
data/Guardfile CHANGED
@@ -8,8 +8,9 @@ guard 'bundler' do
8
8
  watch(/^.+\.gemspec/)
9
9
  end
10
10
 
11
- unit_spec_opts = {spec_paths: ["spec/units"], cli: '-f doc', run_all: {cli: ''}}
12
- acceptance_spec_opts = {spec_paths: ["spec/integration"], cli: '-f doc -t all_adapters', run_all: {cli: '-t all_adapters'}}
11
+ common_rspec_opts = {keep_failed: true, all_after_pass: true}
12
+ unit_spec_opts = common_rspec_opts.merge({spec_paths: ["spec/units"], cli: '-f doc', run_all: {cli: ''}})
13
+ integration_spec_opts = common_rspec_opts.merge({spec_paths: ["spec/integration/#{BrokerConfig.current_adapter}"], cli: '-f doc -t all_adapters', run_all: {cli: '-t all_adapters'}})
13
14
 
14
15
  group 'specs' do
15
16
  guard 'rspec', unit_spec_opts do
@@ -21,15 +22,18 @@ group 'specs' do
21
22
  end
22
23
 
23
24
  group 'integration' do
24
- guard 'rspec', acceptance_spec_opts do
25
+ guard 'rspec', integration_spec_opts do
25
26
  watch(%r{^spec/integration/.+_spec\.rb$})
26
27
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/integration/#{m[1]}_spec.rb" }
27
28
  watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
28
29
  watch('spec/spec_helper.rb') { "spec" }
29
30
  end
31
+ end
30
32
 
33
+ group 'features' do
31
34
  cucumber_cli = "--no-profile --color --format progress --strict --tag @all_adapters,@#{BrokerConfig.current_adapter} --tag ~@wip"
32
- guard 'cucumber', change_format: 'pretty', cli: cucumber_cli do
35
+ cucumber_run_all_cli = "#{cucumber_cli} --tag ~@slow"
36
+ guard 'cucumber', change_format: 'pretty', all_on_start: false, cli: cucumber_cli, run_all: { cli: cucumber_run_all_cli } do
33
37
  watch(%r{^features/.+\.feature$})
34
38
  watch(%r{^features/support/.+$}) { 'features' }
35
39
  watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
data/README.md CHANGED
@@ -2,11 +2,13 @@
2
2
 
3
3
  Easy message queues for ruby
4
4
 
5
- [![Build Status](https://travis-ci.org/soupmatt/message-driver.png?branch=master)](https://travis-ci.org/soupmatt/message-driver)
5
+ [![Gem Version](https://badge.fury.io/rb/message-driver.png)](http://badge.fury.io/rb/message-driver)
6
6
 
7
- [![Dependency Status](https://gemnasium.com/soupmatt/message-driver.png)](https://gemnasium.com/soupmatt/message-driver)
7
+ [![Build Status](https://travis-ci.org/message-driver/message-driver.png?branch=master)](https://travis-ci.org/message-driver/message-driver)
8
8
 
9
- [![Code Climate](https://codeclimate.com/github/soupmatt/message-driver.png)](https://codeclimate.com/github/soupmatt/message-driver)
9
+ [![Dependency Status](https://gemnasium.com/message-driver/message-driver.png)](https://gemnasium.com/message-driver/message-driver)
10
+
11
+ [![Code Climate](https://codeclimate.com/github/message-driver/message-driver.png)](https://codeclimate.com/github/message-driver/message-driver)
10
12
 
11
13
  ## Installation
12
14
 
@@ -14,6 +16,11 @@ Add this line to your application's Gemfile:
14
16
 
15
17
  gem 'message-driver'
16
18
 
19
+ You'll also want to add a driver gem:
20
+
21
+ gem 'bunny'
22
+ gem 'stomp'
23
+
17
24
  And then execute:
18
25
 
19
26
  $ bundle
@@ -22,9 +29,11 @@ Or install it yourself as:
22
29
 
23
30
  $ gem install message-driver
24
31
 
25
- ## Usage
32
+ ## Documentation
33
+
34
+ You can find the main documentation here: https://www.relishapp.com/message-driver/message-driver
26
35
 
27
- TODO: Write usage instructions here
36
+ You can also take a look at the [examples](/examples)
28
37
 
29
38
  ## Contributing
30
39
 
data/Rakefile CHANGED
@@ -1,23 +1,56 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
1
4
  require 'bundler/gem_tasks'
2
5
 
3
6
  require 'rspec/core/rake_task'
4
7
  require 'cucumber/rake/task'
5
8
 
6
- require File.join(File.dirname(__FILE__), 'test_lib', 'broker_config')
9
+ #require File.join(File.dirname(__FILE__), 'test_lib', 'broker_config')
10
+
11
+ namespace :spec do
12
+ desc "Run unit specs"
13
+ RSpec::Core::RakeTask.new(:units) do |t|
14
+ t.pattern = "./spec/units{,/*/**}/*_spec.rb"
15
+ end
16
+
17
+ desc "Run the integration specs"
18
+ RSpec::Core::RakeTask.new(:integrations) do |t|
19
+ t.rspec_opts = "--tag all_adapters"
20
+ t.pattern = "./spec/integration/#{BrokerConfig.current_adapter}{,/*/**}/*_spec.rb"
21
+ end
22
+
23
+ cucumber_opts = "--format progress --tag @all_adapters,@#{BrokerConfig.current_adapter} --tag ~@wip"
24
+ cucumber_opts += " --tag ~@no_ci" if ENV['CI']=='true' && ENV['ADAPTER'] && ENV['ADAPTER'].start_with?('bunny')
25
+ Cucumber::Rake::Task.new(:features) do |t|
26
+ t.cucumber_opts = cucumber_opts
27
+ end
28
+
29
+ desc "run all the specs"
30
+ task :all => [:units, :integrations, :features]
7
31
 
8
- RSpec::Core::RakeTask.new(:spec) do |t|
9
- t.pattern = "./spec/units{,/*/**}/*_spec.rb"
32
+ desc "run all the specs for each adapter"
33
+ task :all_adapters do
34
+ current_adapter = BrokerConfig.current_adapter
35
+ BrokerConfig.all_adapters.each do |adapter|
36
+ set_adapter_under_test(adapter)
37
+ system("rake spec:all")
38
+ end
39
+ set_adapter_under_test(current_adapter)
40
+ end
10
41
  end
11
42
 
12
- RSpec::Core::RakeTask.new(:integrations) do |t|
13
- t.rspec_opts = "--tag all_adapters"
14
- t.pattern = "./spec/integration{,/*/**}/*_spec.rb"
43
+ def set_adapter_under_test(adapter)
44
+ system "echo #{adapter} > #{File.join(File.dirname(__FILE__), '.adapter_under_test')}"
15
45
  end
16
46
 
17
- cucumber_opts = "--format progress --tag @all_adapters,@#{BrokerConfig.current_adapter} --tag ~@wip"
18
- cucumber_opts += " --tag ~@no_travis" if ENV['TRAVIS']=='true' && ENV['ADAPTER']=='bunny'
19
- Cucumber::Rake::Task.new do |t|
20
- t.cucumber_opts = cucumber_opts
47
+ namespace :undertest do
48
+ BrokerConfig.all_adapters.each do |adapter|
49
+ desc "set the adapter under test to #{adapter}"
50
+ task adapter do
51
+ set_adapter_under_test(adapter)
52
+ end
53
+ end
21
54
  end
22
55
 
23
- task :default => [:spec, :integrations, :cucumber]
56
+ task :default => ["spec:all"]
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "message-driver", path: "../.."
4
+
5
+ gem 'bunny'
@@ -0,0 +1,17 @@
1
+ require 'bundler/setup'
2
+ require 'message-driver'
3
+ require 'logger'
4
+
5
+ LOG = Logger.new(STDOUT)
6
+ LOG.level = Logger::DEBUG
7
+
8
+ MessageDriver.configure(
9
+ adapter: "bunny",
10
+ vhost: "message-driver-dev",
11
+ heartbeat_interval: 2,
12
+ logger: LOG
13
+ )
14
+
15
+ MessageDriver::Broker.define do |b|
16
+ b.destination :basic_consumer_producer, "basic.consumer.producer", durable: true
17
+ end
@@ -0,0 +1,24 @@
1
+ require_relative "./common"
2
+
3
+ LOG.info("starting consumer")
4
+
5
+ end_thread = Thread.new do
6
+ Thread.stop
7
+ LOG.info("stopping consumer")
8
+ MessageDriver::Broker.stop
9
+ end
10
+
11
+ ending_proc = proc do
12
+ end_thread.wakeup
13
+ end
14
+
15
+ trap "TERM", &ending_proc
16
+ trap "INT", &ending_proc
17
+
18
+ MessageDriver::Broker.consumer(:basic_consumer) do |message|
19
+ LOG.info("I got a message! #{message.body}")
20
+ end
21
+
22
+ MessageDriver::Client.subscribe(:basic_consumer_producer, :basic_consumer)
23
+
24
+ end_thread.join
@@ -0,0 +1,33 @@
1
+ require_relative "./common"
2
+
3
+ LOG.info("starting producer")
4
+
5
+ stopping = false
6
+
7
+ ending_proc = proc do
8
+ stopping = true
9
+ end
10
+
11
+ trap "TERM", &ending_proc
12
+ trap "INT", &ending_proc
13
+
14
+ counter = 0
15
+
16
+ while !stopping do
17
+ 10.times do
18
+ counter += 1
19
+ begin
20
+ MessageDriver::Client.publish(:basic_consumer_producer, "message #{counter}")
21
+ rescue MessageDriver::ConnectionError => e
22
+ LOG.info("The connection is closed! #{e}")
23
+ sleep 1
24
+ LOG.info("retrying...")
25
+ retry
26
+ end
27
+ end
28
+ LOG.info("sent 10 more messages for a total of #{counter}")
29
+ sleep 1
30
+ end
31
+
32
+ LOG.info("stopping producer")
33
+ MessageDriver::Broker.stop
data/features/.nav CHANGED
@@ -4,9 +4,17 @@
4
4
  - publishing_with_transactions.feature
5
5
  - dynamic_destinations.feature
6
6
  - destination_metadata.feature
7
+ - client_acks.feature
8
+ - logging.feature
9
+ - message_consumers.feature
10
+ - message_consumers
11
+ - auto_ack_consumers.feature
12
+ - manual_ack_consumers.feature
13
+ - transactional_ack_consumers.feature
7
14
  - amqp_specific_features (AMQP-Specific Features):
8
15
  - declaring_amqp_destinations.feature
9
16
  - binding_amqp_destinations.feature
10
17
  - server_named_desitnations.feature
18
+ - requeueing_on_nack.feature
11
19
  - error_handling.feature
12
20
  - Rails.md
@@ -1,6 +1,16 @@
1
- # Change Log
1
+ # Changelog
2
2
 
3
- ## 0.1.0
3
+ ## 0.2.0.rc1 - 2013-09-23
4
+
5
+ * Features
6
+ * Message Consumers
7
+ * Bunny and InMemory adapters
8
+ * Client Acks
9
+ * Bunny adapter
10
+ * Adapters
11
+ * begin work on Stomp 1.1/1.2 adapter
12
+
13
+ ## 0.1.0 - 2013-04-05
4
14
 
5
15
  Initial Release
6
16
 
@@ -1,7 +1,7 @@
1
1
  @bunny
2
2
  Feature: Binding AMQP destinations to exchanges
3
3
  Background:
4
- Given the following broker configuration:
4
+ Given the following broker configuration
5
5
  """ruby
6
6
  MessageDriver::Broker.define do |b|
7
7
  b.destination :direct_exchange, "amq.direct", type: :exchange
@@ -9,10 +9,10 @@ Feature: Binding AMQP destinations to exchanges
9
9
  """
10
10
 
11
11
  Scenario: Binding a queue to an exchange
12
- When I execute the following code:
12
+ When I execute the following code
13
13
  """ruby
14
14
  MessageDriver::Broker.define do |b|
15
- b.destination :my_queue, "my_queue", exclusive: true, bindings: [
15
+ b.destination :my_queue, "my_bound_queue", exclusive: true, bindings: [
16
16
  {source: "amq.direct", args: {routing_key: "test_binding"}},
17
17
  {source: "amq.direct", args: {routing_key: "spec_binding"}}
18
18
  ]
@@ -22,7 +22,7 @@ Feature: Binding AMQP destinations to exchanges
22
22
  publish(:direct_exchange, "Spec Message", {}, {routing_key: "spec_binding"})
23
23
  """
24
24
 
25
- Then I expect to find 2 messages on :my_queue with:
25
+ Then I expect to find the following 2 messages on :my_queue
26
26
  | body |
27
27
  | Test Message |
28
28
  | Spec Message |
@@ -30,21 +30,21 @@ Feature: Binding AMQP destinations to exchanges
30
30
  Scenario: Binding an exchange to an exchange
31
31
  RabbitMQ's AMQP 0.9 extenstions support binding exchanges to exchanges
32
32
 
33
- When I execute the following code:
33
+ When I execute the following code
34
34
  """ruby
35
35
  MessageDriver::Broker.define do |b|
36
36
  b.destination :fanout, "amq.fanout", type: :exchange, bindings: [
37
37
  {source: "amq.direct", args: {routing_key: "test_binding"}},
38
38
  {source: "amq.direct", args: {routing_key: "spec_binding"}}
39
39
  ]
40
- b.destination :my_queue, "my_queue", exclusive: true, bindings: [{source: "amq.fanout"}]
40
+ b.destination :my_queue, "my_bound_queue", exclusive: true, bindings: [{source: "amq.fanout"}]
41
41
  end
42
42
 
43
43
  publish(:direct_exchange, "Test Message", {}, {routing_key: "test_binding"})
44
44
  publish(:direct_exchange, "Spec Message", {}, {routing_key: "spec_binding"})
45
45
  """
46
46
 
47
- Then I expect to find 2 messages on :my_queue with:
47
+ Then I expect to find the following 2 messages on :my_queue
48
48
  | body |
49
49
  | Test Message |
50
50
  | Spec Message |
@@ -7,16 +7,16 @@ Feature: Declaring AMQP exchanges
7
7
  Given I am connected to the broker
8
8
 
9
9
  Scenario: Declaring a direct exchange
10
- When I execute the following code:
10
+ When I execute the following code
11
11
  """ruby
12
12
  MessageDriver::Broker.define do |b|
13
13
  b.destination :my_exchange, "my_exchange", type: :exchange, declare: {type: :direct, auto_delete: true}
14
- b.destination :my_queue, "my_queue", exclusive: true, bindings: [{source: "my_exchange", routing_key: "my_queue"}]
14
+ b.destination :my_queue, "", exclusive: true, bindings: [{source: "my_exchange", routing_key: "my_queue"}]
15
15
  end
16
16
 
17
17
  publish(:my_exchange, "Test My New Exchange", routing_key: "my_queue")
18
18
  """
19
19
 
20
- Then I expect to find 1 message on :my_queue with:
20
+ Then I expect to find the following message on :my_queue
21
21
  | body |
22
22
  | Test My New Exchange |
@@ -0,0 +1,92 @@
1
+ @bunny
2
+ Feature: Nacking Redelievered Messages from a consumer
3
+
4
+ You can configure the consumer to nack a re-delievered message. In this example, we use
5
+ a dead letter exchange to show how things end up working.
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
+ And I have a destination :rabbit_track with no messages on it
26
+
27
+
28
+ Scenario: Raising a DontRequeueError in an auto_ack consumer
29
+ Given I have a message consumer
30
+ """ruby
31
+ MessageDriver::Broker.consumer(:manual_redeliver) do |message|
32
+ publish(:rabbit_track, "#{message.body} Attempt")
33
+ raise "oh nos!"
34
+ end
35
+ """
36
+ And I create a subscription
37
+ """ruby
38
+ MessageDriver::Client.subscribe(:rabbit_work, :manual_redeliver, ack: :auto, retry_redelivered: false)
39
+ """
40
+
41
+ When I send the following messages to :rabbit_work
42
+ | body |
43
+ | Auto Retry 1 |
44
+ | Auto Retry 2 |
45
+ And I let the subscription process
46
+
47
+ Then I expect to find no messages on :rabbit_work
48
+ And I expect to find the following 2 messages on :rabbit_dlq
49
+ | body |
50
+ | Auto Retry 1 |
51
+ | Auto Retry 2 |
52
+ And I expect to find the following 4 messages on :rabbit_track
53
+ | body |
54
+ | Auto Retry 1 Attempt |
55
+ | Auto Retry 2 Attempt |
56
+ | Auto Retry 1 Attempt |
57
+ | Auto Retry 2 Attempt |
58
+
59
+
60
+ Scenario: Raising a DontRequeueError in a transactional consumer
61
+ Given I have a message consumer
62
+ """ruby
63
+ @attempts = 0
64
+ MessageDriver::Broker.consumer(:transactional_redeliver) do |message|
65
+ publish(:rabbit_track, "#{message.body} Attempt")
66
+ @attempts += 1
67
+ raise "oh nos!"
68
+ end
69
+ """
70
+ And I create a subscription
71
+ """ruby
72
+ MessageDriver::Client.subscribe(:rabbit_work, :transactional_redeliver, ack: :transactional, retry_redelivered: false)
73
+ """
74
+
75
+ When I send the following messages to :rabbit_work
76
+ | body |
77
+ | Transactional Redeliver 1 |
78
+ | Transactional Redeliver 2 |
79
+ And I let the subscription process
80
+ And I restart the subscription
81
+ And I let the subscription process
82
+
83
+ Then I expect to find no messages on :rabbit_track
84
+ Then I expect to find no messages on :rabbit_work
85
+ Then I expect the following check to pass
86
+ """ruby
87
+ expect(@attempts).to eq(4)
88
+ """
89
+ Then I expect to find the following 2 messages on :rabbit_dlq
90
+ | body |
91
+ | Transactional Redeliver 1 |
92
+ | Transactional Redeliver 2 |
@@ -0,0 +1,44 @@
1
+ @bunny
2
+ Feature: Controlling requeue on message nack
3
+ You can control whether or not a message is requeued when you nack the message.
4
+ Exact behavior when requeue is false is specific to your broker's setup.
5
+
6
+ Background:
7
+ Given I am connected to the broker
8
+ And I have a destination :source_queue
9
+ And I have the following messages on :source_queue
10
+ | body |
11
+ | Test Message |
12
+
13
+ Scenario: Requeue by default
14
+ When I execute the following code
15
+ """ruby
16
+ message = MessageDriver::Client.pop_message(:source_queue, client_ack: true)
17
+ message.nack
18
+ """
19
+
20
+ Then I expect to find the following message on :source_queue
21
+ | body |
22
+ | Test Message |
23
+
24
+
25
+ Scenario: Requeue is true
26
+ When I execute the following code
27
+ """ruby
28
+ message = MessageDriver::Client.pop_message(:source_queue, client_ack: true)
29
+ message.nack(requeue: true)
30
+ """
31
+
32
+ Then I expect to find the following message on :source_queue
33
+ | body |
34
+ | Test Message |
35
+
36
+
37
+ Scenario: Requeue is false
38
+ When I execute the following code
39
+ """ruby
40
+ message = MessageDriver::Client.pop_message(:source_queue, client_ack: true)
41
+ message.nack(requeue: false)
42
+ """
43
+
44
+ Then I expect to find no messages on :source_queue
@@ -9,7 +9,7 @@ Feature: Server-Named Destinations
9
9
  Scenario: Creating a server-named queue
10
10
  I expect my destination to have the queue name given to it by the server
11
11
 
12
- When I execute the following code:
12
+ When I execute the following code
13
13
  """ruby
14
14
  destination = MessageDriver::Broker.dynamic_destination("", exclusive: true)
15
15
  expect(destination.name).to_not be_empty
@@ -18,18 +18,18 @@ Feature: Server-Named Destinations
18
18
  Then I expect to have no errors
19
19
 
20
20
  Scenario: sending and receiving messages through a server-named queue
21
- Given the following broker configuration:
21
+ Given the following broker configuration
22
22
  """ruby
23
23
  MessageDriver::Broker.define do |b|
24
- b.destination :my_queue, "my_queue", exclusive: true
24
+ b.destination :my_queue, "", exclusive: true
25
25
  end
26
26
  """
27
27
 
28
- When I execute the following code:
28
+ When I execute the following code
29
29
  """ruby
30
30
  publish(:my_queue, "server-named queue message")
31
31
  """
32
32
 
33
- Then I expect to find 1 message on :my_queue with:
33
+ Then I expect to find the following message on :my_queue
34
34
  | body |
35
35
  | server-named queue message |