message-driver 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +18 -0
  3. data/.rubocop_todo.yml +160 -0
  4. data/.travis.yml +5 -4
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +9 -8
  7. data/Guardfile +14 -7
  8. data/README.md +2 -0
  9. data/Rakefile +16 -10
  10. data/examples/basic_producer_and_consumer/Gemfile +2 -2
  11. data/examples/basic_producer_and_consumer/common.rb +3 -3
  12. data/examples/basic_producer_and_consumer/consumer.rb +5 -5
  13. data/examples/basic_producer_and_consumer/producer.rb +7 -7
  14. data/features/CHANGELOG.md +5 -0
  15. data/features/message_consumers/transactional_ack_consumers.feature +1 -0
  16. data/features/rabbitmq_specific_features/publisher_acknowledgements.feature +51 -0
  17. data/features/step_definitions/error_handling_steps.rb +2 -2
  18. data/features/step_definitions/logging_steps.rb +4 -4
  19. data/features/step_definitions/message_consumers_steps.rb +8 -8
  20. data/features/step_definitions/rabbitmq_specific_steps.rb +10 -0
  21. data/features/step_definitions/steps.rb +15 -15
  22. data/features/support/env.rb +3 -0
  23. data/features/support/firewall_helper.rb +5 -6
  24. data/features/support/message_table_matcher.rb +3 -4
  25. data/features/support/no_error_matcher.rb +3 -3
  26. data/features/support/test_runner.rb +11 -3
  27. data/features/support/transforms.rb +1 -1
  28. data/lib/message-driver.rb +1 -1
  29. data/lib/message_driver.rb +0 -1
  30. data/lib/message_driver/adapters/base.rb +10 -10
  31. data/lib/message_driver/adapters/bunny_adapter.rb +57 -30
  32. data/lib/message_driver/adapters/in_memory_adapter.rb +4 -5
  33. data/lib/message_driver/adapters/stomp_adapter.rb +4 -6
  34. data/lib/message_driver/broker.rb +5 -4
  35. data/lib/message_driver/client.rb +6 -6
  36. data/lib/message_driver/destination.rb +2 -2
  37. data/lib/message_driver/errors.rb +1 -4
  38. data/lib/message_driver/logging.rb +1 -1
  39. data/lib/message_driver/message.rb +2 -2
  40. data/lib/message_driver/subscription.rb +1 -1
  41. data/lib/message_driver/version.rb +1 -1
  42. data/lib/{message_driver/vendor → vendor}/.document +0 -0
  43. data/lib/vendor/nesty.rb +1 -0
  44. data/lib/vendor/nesty/nested_error.rb +28 -0
  45. data/message-driver.gemspec +15 -14
  46. data/spec/integration/bunny/amqp_integration_spec.rb +43 -43
  47. data/spec/integration/bunny/bunny_adapter_spec.rb +117 -101
  48. data/spec/integration/in_memory/in_memory_adapter_spec.rb +35 -35
  49. data/spec/integration/stomp/stomp_adapter_spec.rb +42 -42
  50. data/spec/spec_helper.rb +4 -1
  51. data/spec/support/shared/adapter_examples.rb +7 -7
  52. data/spec/support/shared/client_ack_examples.rb +6 -6
  53. data/spec/support/shared/context_examples.rb +4 -4
  54. data/spec/support/shared/destination_examples.rb +10 -10
  55. data/spec/support/shared/subscription_examples.rb +29 -29
  56. data/spec/support/shared/transaction_examples.rb +10 -10
  57. data/spec/units/message_driver/adapters/base_spec.rb +19 -19
  58. data/spec/units/message_driver/broker_spec.rb +57 -58
  59. data/spec/units/message_driver/client_spec.rb +84 -84
  60. data/spec/units/message_driver/destination_spec.rb +4 -4
  61. data/spec/units/message_driver/message_spec.rb +19 -19
  62. data/spec/units/message_driver/subscription_spec.rb +4 -4
  63. data/test_lib/broker_config.rb +2 -2
  64. metadata +27 -6
  65. data/lib/message_driver/vendor/nesty.rb +0 -1
  66. data/lib/message_driver/vendor/nesty/nested_error.rb +0 -26
@@ -9,7 +9,6 @@ module MessageDriver
9
9
 
10
10
  module Adapters
11
11
  class InMemoryAdapter < Base
12
-
13
12
  class Message < MessageDriver::Message::Base
14
13
  end
15
14
 
@@ -30,7 +29,6 @@ module MessageDriver
30
29
  end
31
30
 
32
31
  class Destination < MessageDriver::Destination::Base
33
-
34
32
  def subscription
35
33
  adapter.subscription_for(name)
36
34
  end
@@ -39,7 +37,7 @@ module MessageDriver
39
37
  message_queue.size
40
38
  end
41
39
 
42
- def pop_message(options={})
40
+ def pop_message(_options={})
43
41
  message_queue.shift
44
42
  end
45
43
 
@@ -63,16 +61,17 @@ module MessageDriver
63
61
  end
64
62
 
65
63
  private
64
+
66
65
  def message_queue
67
66
  adapter.message_queue_for(name)
68
67
  end
69
68
  end
70
69
 
71
- def initialize(broker, config={})
70
+ def initialize(broker, _config={})
72
71
  @broker = broker
73
72
  @destinations = {}
74
73
  @message_store = Hash.new { |h,k| h[k] = [] }
75
- @subscriptions = Hash.new
74
+ @subscriptions = {}
76
75
  end
77
76
 
78
77
  def build_context
@@ -10,7 +10,6 @@ module MessageDriver
10
10
 
11
11
  module Adapters
12
12
  class StompAdapter < Base
13
-
14
13
  class Message < MessageDriver::Message::Base
15
14
  attr_reader :stomp_message
16
15
  def initialize(ctx, stomp_message)
@@ -20,7 +19,6 @@ module MessageDriver
20
19
  end
21
20
 
22
21
  class Destination < MessageDriver::Destination::Base
23
-
24
22
  end
25
23
 
26
24
  attr_reader :config, :poll_timeout
@@ -32,7 +30,7 @@ module MessageDriver
32
30
  @config = config.symbolize_keys
33
31
  connect_headers = @config[:connect_headers] ||= {}
34
32
  connect_headers.symbolize_keys
35
- connect_headers[:"accept-version"] = "1.1,1.2"
33
+ connect_headers[:"accept-version"] = '1.1,1.2'
36
34
 
37
35
  vhost = @config.delete(:vhost)
38
36
  connect_headers[:host] = vhost if vhost
@@ -50,13 +48,13 @@ module MessageDriver
50
48
  #end
51
49
 
52
50
  def create_destination(name, dest_options={}, message_props={})
53
- unless name.start_with?("/")
51
+ unless name.start_with?('/')
54
52
  name = "/queue/#{name}"
55
53
  end
56
54
  Destination.new(adapter, name, dest_options, message_props)
57
55
  end
58
56
 
59
- def publish(destination, body, headers={}, properties={})
57
+ def publish(destination, body, headers={}, _properties={})
60
58
  with_connection do |connection|
61
59
  connection.publish(destination.name, body, headers)
62
60
  end
@@ -119,7 +117,7 @@ module MessageDriver
119
117
  required = Gem::Requirement.create('~> 1.3.1')
120
118
  current = Gem::Version.create(Stomp::Version::STRING)
121
119
  unless required.satisfied_by? current
122
- raise MessageDriver::Error, "stomp 1.3.1 or a later version of the 1.3.x series is required for the stomp adapter"
120
+ raise MessageDriver::Error, 'stomp 1.3.1 or a later version of the 1.3.x series is required for the stomp adapter'
123
121
  end
124
122
  end
125
123
  end
@@ -27,7 +27,7 @@ module MessageDriver
27
27
  end
28
28
 
29
29
  def client(name)
30
- unless result = clients[name]
30
+ unless (result = clients[name])
31
31
  result = clients[name] = Client.for_broker(name)
32
32
  end
33
33
  result
@@ -63,6 +63,7 @@ module MessageDriver
63
63
  end
64
64
 
65
65
  private
66
+
66
67
  def brokers
67
68
  @brokers ||= { }
68
69
  end
@@ -85,7 +86,7 @@ module MessageDriver
85
86
  @configuration = options
86
87
  @destinations = {}
87
88
  @consumers = {}
88
- logger.debug "MessageDriver configured successfully!"
89
+ logger.debug 'MessageDriver configured successfully!'
89
90
  end
90
91
 
91
92
  def logger
@@ -123,7 +124,7 @@ module MessageDriver
123
124
  end
124
125
 
125
126
  def consumer(key, &block)
126
- raise MessageDriver::Error, "you must provide a block" unless block_given?
127
+ raise MessageDriver::Error, 'you must provide a block' unless block_given?
127
128
  @consumers[key] = block
128
129
  end
129
130
 
@@ -144,7 +145,7 @@ module MessageDriver
144
145
  def resolve_adapter(adapter, options)
145
146
  case adapter
146
147
  when nil
147
- raise "you must specify an adapter"
148
+ raise 'you must specify an adapter'
148
149
  when Symbol, String
149
150
  resolve_adapter(find_adapter_class(adapter), options)
150
151
  when Class
@@ -54,7 +54,7 @@ module MessageDriver
54
54
  broker.find_consumer(consumer)
55
55
  end
56
56
 
57
- def with_message_transaction(options={}, &block)
57
+ def with_message_transaction(options={})
58
58
  wrapper = fetch_context_wrapper
59
59
  wrapper.increment_transaction_depth
60
60
  begin
@@ -76,7 +76,7 @@ module MessageDriver
76
76
  yield
77
77
  end
78
78
  else
79
- logger.debug("this adapter does not support transactions")
79
+ logger.debug('this adapter does not support transactions')
80
80
  yield
81
81
  end
82
82
  ensure
@@ -89,7 +89,7 @@ module MessageDriver
89
89
  ctx.nil? ? nil : ctx.ctx
90
90
  end
91
91
 
92
- def with_adapter_context(adapter_context, &block)
92
+ def with_adapter_context(adapter_context)
93
93
  old_ctx, Thread.current[adapter_context_key] = fetch_context_wrapper(false), build_context_wrapper(adapter_context)
94
94
  begin
95
95
  yield
@@ -114,13 +114,13 @@ module MessageDriver
114
114
  Broker::DEFAULT_BROKER_NAME
115
115
  end
116
116
 
117
- def for_broker(_broker_name)
118
- Module.new do |mod|
117
+ def for_broker(name)
118
+ Module.new do
119
119
  include Client
120
120
  extend self
121
121
 
122
122
  define_method :broker_name do
123
- _broker_name
123
+ name
124
124
  end
125
125
  end
126
126
  end
@@ -18,7 +18,7 @@ module MessageDriver
18
18
  adapter.broker.client.pop_message(self, options)
19
19
  end
20
20
 
21
- def after_initialize(adapter_context)
21
+ def after_initialize(_adapter_context)
22
22
  #does nothing, feel free to override as needed
23
23
  end
24
24
 
@@ -26,7 +26,7 @@ module MessageDriver
26
26
  raise "#message_count is not supported by #{self.class}"
27
27
  end
28
28
 
29
- def subscribe(&consumer)
29
+ def subscribe(&_consumer)
30
30
  raise "#subscribe is not supported by #{self.class}"
31
31
  end
32
32
  end
@@ -1,7 +1,4 @@
1
- vendor = File.expand_path('../vendor', __FILE__)
2
- $:.unshift(vendor) unless $:.include?(vendor)
3
-
4
- require 'nesty'
1
+ require 'vendor/nesty'
5
2
 
6
3
  module MessageDriver
7
4
  class Error < StandardError; end
@@ -7,7 +7,7 @@ module MessageDriver
7
7
  end
8
8
 
9
9
  def exception_to_str(e)
10
- (["#{e.class}: #{e.to_s}"] + e.backtrace).join("\n ")
10
+ (["#{e.class}: #{e}"] + e.backtrace).join("\n ")
11
11
  end
12
12
 
13
13
  def message_with_exception(message, e)
@@ -16,7 +16,7 @@ module MessageDriver
16
16
  if ctx.supports_client_acks?
17
17
  ctx.ack_message(self, options)
18
18
  else
19
- logger.debug("this adapter does not support client acks")
19
+ logger.debug('this adapter does not support client acks')
20
20
  end
21
21
  end
22
22
 
@@ -24,7 +24,7 @@ module MessageDriver
24
24
  if ctx.supports_client_acks?
25
25
  ctx.nack_message(self, options)
26
26
  else
27
- logger.debug("this adapter does not support client acks")
27
+ logger.debug('this adapter does not support client acks')
28
28
  end
29
29
  end
30
30
  end
@@ -12,7 +12,7 @@ module MessageDriver
12
12
  end
13
13
 
14
14
  def unsubscribe
15
- raise "must be implemented in subclass"
15
+ raise 'must be implemented in subclass'
16
16
  end
17
17
  end
18
18
  end
@@ -1,5 +1,5 @@
1
1
  module Message
2
2
  module Driver
3
- VERSION = "0.3.0"
3
+ VERSION = '0.4.0'
4
4
  end
5
5
  end
File without changes
@@ -0,0 +1 @@
1
+ require 'vendor/nesty/nested_error'
@@ -0,0 +1,28 @@
1
+ module MessageDriver
2
+ module Nesty
3
+ module NestedError
4
+ attr_reader :nested, :raw_backtrace
5
+
6
+ def initialize(msg = nil, nested)
7
+ super(msg)
8
+ @nested = nested
9
+ end
10
+
11
+ def set_backtrace(backtrace)
12
+ @raw_backtrace = backtrace
13
+ if nested
14
+ backtrace = backtrace - nested_raw_backtrace
15
+ backtrace += ["#{nested.backtrace.first}: #{nested.message} (#{nested.class.name})"]
16
+ backtrace += nested.backtrace[1..-1] || []
17
+ end
18
+ super(backtrace)
19
+ end
20
+
21
+ private
22
+
23
+ def nested_raw_backtrace
24
+ nested.respond_to?(:raw_backtrace) ? nested.raw_backtrace : nested.backtrace
25
+ end
26
+ end
27
+ end
28
+ end
@@ -4,24 +4,25 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'message_driver/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
- gem.name = "message-driver"
7
+ gem.name = 'message-driver'
8
8
  gem.version = Message::Driver::VERSION
9
- gem.authors = ["Matt Campbell"]
10
- gem.email = ["message-driver@soupmatt.com"]
11
- gem.description = %q{Easy message queues for ruby using AMQ, STOMP and others}
12
- gem.summary = %q{Easy message queues for ruby}
13
- gem.homepage = "https://github.com/message-driver/message-driver"
14
- gem.license = "MIT"
9
+ gem.authors = ['Matt Campbell']
10
+ gem.email = ['message-driver@soupmatt.com']
11
+ gem.description = 'Easy message queues for ruby using AMQ, STOMP and others'
12
+ gem.summary = 'Easy message queues for ruby'
13
+ gem.homepage = 'https://github.com/message-driver/message-driver'
14
+ gem.license = 'MIT'
15
15
 
16
- gem.files = `git ls-files`.split($/)
17
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
16
+ gem.files = `git ls-files`.split($RS)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
- gem.require_paths = ["lib"]
19
+ gem.require_paths = %w(lib)
20
20
 
21
21
  gem.required_ruby_version = '>= 1.9.2'
22
22
 
23
- gem.add_development_dependency "rake"
24
- gem.add_development_dependency "rspec", "~> 2.14.0"
25
- gem.add_development_dependency "cucumber"
26
- gem.add_development_dependency "aruba"
23
+ gem.add_development_dependency 'rake'
24
+ gem.add_development_dependency 'rspec', '~> 2.14.0'
25
+ gem.add_development_dependency 'cucumber'
26
+ gem.add_development_dependency 'aruba'
27
+ gem.add_development_dependency 'rubocop'
27
28
  end
@@ -1,11 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "AMQP Integration", :bunny, type: :integration do
3
+ describe 'AMQP Integration', :bunny, type: :integration do
4
4
  let!(:broker) { MessageDriver::Broker.configure BrokerConfig.config }
5
5
 
6
6
  context "when a queue can't be found" do
7
- let(:queue_name) { "my.lost.queue" }
8
- it "raises a MessageDriver::QueueNotFound error" do
7
+ let(:queue_name) { 'my.lost.queue' }
8
+ it 'raises a MessageDriver::QueueNotFound error' do
9
9
  expect {
10
10
  broker.dynamic_destination(queue_name, passive: true)
11
11
  }.to raise_error(MessageDriver::QueueNotFound) do |err|
@@ -15,40 +15,40 @@ describe "AMQP Integration", :bunny, type: :integration do
15
15
  end
16
16
  end
17
17
 
18
- context "when a channel level exception occurs" do
19
- it "raises a MessageDriver::WrappedError error" do
18
+ context 'when a channel level exception occurs' do
19
+ it 'raises a MessageDriver::WrappedError error' do
20
20
  expect {
21
- broker.dynamic_destination("not.a.queue", passive: true)
21
+ broker.dynamic_destination('not.a.queue', passive: true)
22
22
  }.to raise_error(MessageDriver::WrappedError) { |err| err.nested.should be_a Bunny::ChannelLevelException }
23
23
  end
24
24
 
25
- it "reestablishes the channel transparently" do
25
+ it 'reestablishes the channel transparently' do
26
26
  expect {
27
- broker.dynamic_destination("not.a.queue", passive: true)
27
+ broker.dynamic_destination('not.a.queue', passive: true)
28
28
  }.to raise_error(MessageDriver::WrappedError)
29
29
  expect {
30
- broker.dynamic_destination("", exclusive: true)
30
+ broker.dynamic_destination('', exclusive: true)
31
31
  }.to_not raise_error
32
32
  end
33
33
 
34
- context "when in a transaction" do
35
- it "sets the channel_context as rollback-only until the transaction is finished" do
34
+ context 'when in a transaction' do
35
+ it 'sets the channel_context as rollback-only until the transaction is finished' do
36
36
  MessageDriver::Client.with_message_transaction do
37
37
  expect {
38
- broker.dynamic_destination("not.a.queue", passive: true)
38
+ broker.dynamic_destination('not.a.queue', passive: true)
39
39
  }.to raise_error(MessageDriver::WrappedError)
40
40
  expect {
41
- broker.dynamic_destination("", exclusive: true)
41
+ broker.dynamic_destination('', exclusive: true)
42
42
  }.to raise_error(MessageDriver::TransactionRollbackOnly)
43
43
  end
44
44
  expect {
45
- broker.dynamic_destination("", exclusive: true)
45
+ broker.dynamic_destination('', exclusive: true)
46
46
  }.to_not raise_error
47
47
  end
48
48
  end
49
49
  end
50
50
 
51
- context "when the broker connection fails", pending: "these spec are busted" do
51
+ context 'when the broker connection fails', pending: 'these spec are busted' do
52
52
  def disrupt_connection
53
53
  #yes, this is very implementation specific
54
54
  broker.adapter.connection.instance_variable_get(:@transport).close
@@ -58,85 +58,85 @@ describe "AMQP Integration", :bunny, type: :integration do
58
58
  broker.dynamic_destination(queue_name, exclusive: true)
59
59
  end
60
60
 
61
- it "raises a MessageDriver::ConnectionError" do
62
- dest = create_destination("test_queue")
61
+ it 'raises a MessageDriver::ConnectionError' do
62
+ dest = create_destination('test_queue')
63
63
  disrupt_connection
64
64
  expect {
65
- dest.publish("Reconnection Test")
65
+ dest.publish('Reconnection Test')
66
66
  }.to raise_error(MessageDriver::ConnectionError) do |err|
67
67
  expect(err.nested).to be_a Bunny::NetworkErrorWrapper
68
68
  end
69
69
  end
70
70
 
71
- it "seemlessly reconnects" do
72
- dest = create_destination("seemless.reconnect.queue")
71
+ it 'seemlessly reconnects' do
72
+ dest = create_destination('seemless.reconnect.queue')
73
73
  disrupt_connection
74
74
  expect {
75
- dest.publish("Reconnection Test 1")
75
+ dest.publish('Reconnection Test 1')
76
76
  }.to raise_error(MessageDriver::ConnectionError)
77
- dest = create_destination("seemless.reconnect.queue")
78
- dest.publish("Reconnection Test 2")
77
+ dest = create_destination('seemless.reconnect.queue')
78
+ dest.publish('Reconnection Test 2')
79
79
  msg = dest.pop_message
80
80
  expect(msg).to_not be_nil
81
- expect(msg.body).to eq("Reconnection Test 2")
81
+ expect(msg.body).to eq('Reconnection Test 2')
82
82
  end
83
83
 
84
- context "when in a transaction" do
85
- it "raises a MessageDriver::ConnectionError" do
84
+ context 'when in a transaction' do
85
+ it 'raises a MessageDriver::ConnectionError' do
86
86
  expect {
87
87
  MessageDriver::Client.with_message_transaction do
88
88
  disrupt_connection
89
- broker.dynamic_destination("", exclusive: true)
89
+ broker.dynamic_destination('', exclusive: true)
90
90
  end
91
91
  }.to raise_error(MessageDriver::ConnectionError)
92
92
  end
93
93
 
94
- it "sets the channel_context as rollback-only until the transaction is finished" do
94
+ it 'sets the channel_context as rollback-only until the transaction is finished' do
95
95
  MessageDriver::Client.with_message_transaction do
96
96
  disrupt_connection
97
97
  expect {
98
- broker.dynamic_destination("", exclusive: true)
98
+ broker.dynamic_destination('', exclusive: true)
99
99
  }.to raise_error(MessageDriver::ConnectionError)
100
100
  expect {
101
- broker.dynamic_destination("", exclusive: true)
101
+ broker.dynamic_destination('', exclusive: true)
102
102
  }.to raise_error(MessageDriver::TransactionRollbackOnly)
103
103
  end
104
104
  expect {
105
- broker.dynamic_destination("", exclusive: true)
105
+ broker.dynamic_destination('', exclusive: true)
106
106
  }.to_not raise_error
107
107
  end
108
108
  end
109
109
  end
110
110
 
111
- context "when an unhandled expection occurs in a transaction" do
112
- let(:destination) { broker.dynamic_destination("", exclusive: true) }
111
+ context 'when an unhandled expection occurs in a transaction' do
112
+ let(:destination) { broker.dynamic_destination('', exclusive: true) }
113
113
 
114
- it "rolls back the transaction" do
114
+ it 'rolls back the transaction' do
115
115
  expect {
116
116
  MessageDriver::Client.with_message_transaction do
117
- destination.publish("Test Message")
118
- raise "unhandled error"
117
+ destination.publish('Test Message')
118
+ raise 'unhandled error'
119
119
  end
120
- }.to raise_error "unhandled error"
120
+ }.to raise_error 'unhandled error'
121
121
  expect(destination.pop_message).to be_nil
122
122
  end
123
123
 
124
- it "allows the next transaction to continue" do
124
+ it 'allows the next transaction to continue' do
125
125
  expect {
126
126
  MessageDriver::Client.with_message_transaction do
127
- destination.publish("Test Message 1")
128
- raise "unhandled error"
127
+ destination.publish('Test Message 1')
128
+ raise 'unhandled error'
129
129
  end
130
- }.to raise_error "unhandled error"
130
+ }.to raise_error 'unhandled error'
131
131
  expect(destination.pop_message).to be_nil
132
132
 
133
133
  MessageDriver::Client.with_message_transaction do
134
- destination.publish("Test Message 2")
134
+ destination.publish('Test Message 2')
135
135
  end
136
136
 
137
137
  msg = destination.pop_message
138
138
  expect(msg).to_not be_nil
139
- expect(msg.body).to eq("Test Message 2")
139
+ expect(msg.body).to eq('Test Message 2')
140
140
  end
141
141
  end
142
142
  end