hutch 0.21.0-java → 0.25.0-java

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 (55) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +11 -12
  5. data/.yardopts +5 -0
  6. data/CHANGELOG.md +118 -1
  7. data/Gemfile +15 -4
  8. data/Guardfile +13 -4
  9. data/README.md +274 -24
  10. data/Rakefile +8 -1
  11. data/hutch.gemspec +6 -7
  12. data/lib/hutch.rb +11 -8
  13. data/lib/hutch/adapters/march_hare.rb +1 -1
  14. data/lib/hutch/broker.rb +113 -110
  15. data/lib/hutch/cli.rb +42 -11
  16. data/lib/hutch/config.rb +209 -59
  17. data/lib/hutch/error_handlers.rb +1 -0
  18. data/lib/hutch/error_handlers/airbrake.rb +44 -16
  19. data/lib/hutch/error_handlers/base.rb +15 -0
  20. data/lib/hutch/error_handlers/honeybadger.rb +33 -18
  21. data/lib/hutch/error_handlers/logger.rb +12 -6
  22. data/lib/hutch/error_handlers/opbeat.rb +30 -0
  23. data/lib/hutch/error_handlers/sentry.rb +14 -6
  24. data/lib/hutch/logging.rb +5 -5
  25. data/lib/hutch/publisher.rb +75 -0
  26. data/lib/hutch/tracers.rb +1 -0
  27. data/lib/hutch/tracers/opbeat.rb +37 -0
  28. data/lib/hutch/version.rb +1 -1
  29. data/lib/hutch/waiter.rb +104 -0
  30. data/lib/hutch/worker.rb +50 -66
  31. data/lib/yard-settings/handler.rb +38 -0
  32. data/lib/yard-settings/yard-settings.rb +2 -0
  33. data/spec/hutch/broker_spec.rb +162 -77
  34. data/spec/hutch/cli_spec.rb +16 -3
  35. data/spec/hutch/config_spec.rb +83 -22
  36. data/spec/hutch/error_handlers/airbrake_spec.rb +25 -10
  37. data/spec/hutch/error_handlers/honeybadger_spec.rb +24 -2
  38. data/spec/hutch/error_handlers/logger_spec.rb +14 -1
  39. data/spec/hutch/error_handlers/opbeat_spec.rb +37 -0
  40. data/spec/hutch/error_handlers/sentry_spec.rb +18 -1
  41. data/spec/hutch/logger_spec.rb +12 -6
  42. data/spec/hutch/waiter_spec.rb +51 -0
  43. data/spec/hutch/worker_spec.rb +33 -4
  44. data/spec/spec_helper.rb +7 -5
  45. data/spec/tracers/opbeat_spec.rb +44 -0
  46. data/templates/default/class/html/settings.erb +0 -0
  47. data/templates/default/class/setup.rb +4 -0
  48. data/templates/default/fulldoc/html/css/hutch.css +13 -0
  49. data/templates/default/layout/html/setup.rb +7 -0
  50. data/templates/default/method_details/html/settings.erb +5 -0
  51. data/templates/default/method_details/setup.rb +4 -0
  52. data/templates/default/method_details/text/settings.erb +0 -0
  53. data/templates/default/module/html/settings.erb +40 -0
  54. data/templates/default/module/setup.rb +4 -0
  55. metadata +41 -38
@@ -2,17 +2,18 @@ require 'hutch/message'
2
2
  require 'hutch/logging'
3
3
  require 'hutch/broker'
4
4
  require 'hutch/acknowledgements/nack_on_all_failures'
5
+ require 'hutch/waiter'
5
6
  require 'carrot-top'
7
+ require 'securerandom'
6
8
 
7
9
  module Hutch
8
10
  class Worker
9
11
  include Logging
10
12
 
11
- SHUTDOWN_SIGNALS = %w(QUIT TERM INT)
12
-
13
- def initialize(broker, consumers)
13
+ def initialize(broker, consumers, setup_procs)
14
14
  @broker = broker
15
15
  self.consumers = consumers
16
+ self.setup_procs = setup_procs
16
17
  end
17
18
 
18
19
  # Run the main event loop. The consumers will be set up with queues, and
@@ -20,46 +21,11 @@ module Hutch
20
21
  # never returns.
21
22
  def run
22
23
  setup_queues
24
+ setup_procs.each(&:call)
23
25
 
24
- # Set up signal handlers for graceful shutdown
25
- register_signal_handlers
26
-
27
- main_loop
28
- end
29
-
30
- def main_loop
31
- if defined?(JRUBY_VERSION)
32
- # Binds shutdown listener to notify main thread if channel was closed
33
- bind_shutdown_handler
34
-
35
- handle_signals until shutdown_not_called?(0.1)
36
- else
37
- # Take a break from Thread#join every 0.1 seconds to check if we've
38
- # been sent any signals
39
- handle_signals until @broker.wait_on_threads(0.1)
40
- end
41
- end
42
-
43
- # Register handlers for SIG{QUIT,TERM,INT} to shut down the worker
44
- # gracefully. Forceful shutdowns are very bad!
45
- def register_signal_handlers
46
- Thread.main[:signal_queue] = []
47
- supported_shutdown_signals.each do |sig|
48
- # This needs to be reentrant, so we queue up signals to be handled
49
- # in the run loop, rather than acting on signals here
50
- trap(sig) do
51
- Thread.main[:signal_queue] << sig
52
- end
53
- end
54
- end
26
+ Waiter.wait_until_signaled
55
27
 
56
- # Handle any pending signals
57
- def handle_signals
58
- signal = Thread.main[:signal_queue].shift
59
- if signal
60
- logger.info "caught sig#{signal.downcase}, stopping hutch..."
61
- stop
62
- end
28
+ stop
63
29
  end
64
30
 
65
31
  # Stop a running worker by killing all subscriber threads.
@@ -67,36 +33,24 @@ module Hutch
67
33
  @broker.stop
68
34
  end
69
35
 
70
- # Binds shutdown handler, called if channel is closed or network Failed
71
- def bind_shutdown_handler
72
- @broker.channel.on_shutdown do
73
- Thread.main[:shutdown_received] = true
74
- end
75
- end
76
-
77
- # Checks if shutdown handler was called, then sleeps for interval
78
- def shutdown_not_called?(interval)
79
- if Thread.main[:shutdown_received]
80
- true
81
- else
82
- sleep(interval)
83
- false
84
- end
85
- end
86
-
87
36
  # Set up the queues for each of the worker's consumers.
88
37
  def setup_queues
89
38
  logger.info 'setting up queues'
90
- @consumers.each { |consumer| setup_queue(consumer) }
39
+ vetted = @consumers.reject { |c| group_configured? && group_restricted?(c) }
40
+ vetted.each do |c|
41
+ setup_queue(c)
42
+ end
91
43
  end
92
44
 
93
45
  # Bind a consumer's routing keys to its queue, and set up a subscription to
94
46
  # receive messages sent to the queue.
95
47
  def setup_queue(consumer)
48
+ logger.info "setting up queue: #{consumer.get_queue_name}"
49
+
96
50
  queue = @broker.queue(consumer.get_queue_name, consumer.get_arguments)
97
51
  @broker.bind_queue(queue, consumer.routing_keys)
98
52
 
99
- queue.subscribe(manual_ack: true) do |*args|
53
+ queue.subscribe(consumer_tag: unique_consumer_tag, manual_ack: true) do |*args|
100
54
  delivery_info, properties, payload = Hutch::Adapter.decode_message(*args)
101
55
  handle_message(consumer, delivery_info, properties, payload)
102
56
  end
@@ -106,7 +60,7 @@ module Hutch
106
60
  # for wrapping up the message and passing it to the consumer.
107
61
  def handle_message(consumer, delivery_info, properties, payload)
108
62
  serializer = consumer.get_serializer || Hutch::Config[:serializer]
109
- logger.info {
63
+ logger.debug {
110
64
  spec = serializer.binary? ? "#{payload.bytesize} bytes" : "#{payload}"
111
65
  "message(#{properties.message_id || '-'}): " +
112
66
  "routing key: #{delivery_info.routing_key}, " +
@@ -120,16 +74,16 @@ module Hutch
120
74
  @broker.ack(delivery_info.delivery_tag)
121
75
  rescue => ex
122
76
  acknowledge_error(delivery_info, properties, @broker, ex)
123
- handle_error(properties.message_id, payload, consumer, ex)
77
+ handle_error(properties, payload, consumer, ex)
124
78
  end
125
79
 
126
80
  def with_tracing(klass)
127
81
  Hutch::Config[:tracer].new(klass)
128
82
  end
129
83
 
130
- def handle_error(message_id, payload, consumer, ex)
84
+ def handle_error(*args)
131
85
  Hutch::Config[:error_handlers].each do |backend|
132
- backend.handle(message_id, payload, consumer, ex)
86
+ backend.handle(*args)
133
87
  end
134
88
  end
135
89
 
@@ -154,8 +108,38 @@ module Hutch
154
108
 
155
109
  private
156
110
 
157
- def supported_shutdown_signals
158
- SHUTDOWN_SIGNALS.keep_if { |s| Signal.list.keys.include? s }.map(&:to_sym)
111
+ def group_configured?
112
+ if group.present? && consumer_groups.blank?
113
+ logger.info 'Consumer groups are blank'
114
+ end
115
+ group.present?
116
+ end
117
+
118
+ def group_restricted?(consumer)
119
+ consumers_to_load = consumer_groups[group]
120
+ if consumers_to_load
121
+ !allowed_consumers.include?(consumer.name)
122
+ else
123
+ true
124
+ end
125
+ end
126
+
127
+ def group
128
+ Hutch::Config[:group]
129
+ end
130
+
131
+ def consumer_groups
132
+ Hutch::Config[:consumer_groups]
133
+ end
134
+
135
+ attr_accessor :setup_procs
136
+
137
+ def unique_consumer_tag
138
+ prefix = Hutch::Config[:consumer_tag_prefix]
139
+ unique_part = SecureRandom.uuid
140
+ "#{prefix}-#{unique_part}".tap do |tag|
141
+ raise "Tag must be 255 bytes long at most, current one is #{tag.bytesize} ('#{tag}')" if tag.bytesize > 255
142
+ end
159
143
  end
160
144
  end
161
145
  end
@@ -0,0 +1,38 @@
1
+ # :nodoc:
2
+ class SettingsHandlerBase < YARD::Handlers::Ruby::Base
3
+ handles method_call :string_setting
4
+ handles method_call :number_setting
5
+ handles method_call :boolean_setting
6
+
7
+ namespace_only
8
+
9
+ def process
10
+ name = statement.parameters.first.jump(:tstring_content, :ident).source
11
+ object = YARD::CodeObjects::MethodObject.new(namespace, name)
12
+ register(object)
13
+
14
+ # Modify the code object for the new instance method
15
+ object.dynamic = true
16
+ # Add custom metadata to the object
17
+ object['custom_field'] = '(Found using method_missing)'
18
+
19
+ # Module-level configuration notes
20
+ hutch_config = YARD::CodeObjects::ModuleObject.new(:root, "Hutch::Config")
21
+ collection_name = statement.first.first
22
+ default_value = statement.parameters[1].jump(:tstring_content, :ident).source
23
+
24
+ (hutch_config['setting_rows'] ||= []) << {
25
+ name: name,
26
+ default_value: default_value,
27
+ type: collection_name.sub('_setting', '').capitalize,
28
+ description: object.docstring,
29
+ first_line_of_description: first_line_of_description(object)
30
+ }
31
+ end
32
+
33
+ def first_line_of_description(object)
34
+ return '' if object.docstring.blank?
35
+
36
+ object.docstring.lines.first
37
+ end
38
+ end
@@ -0,0 +1,2 @@
1
+ YARD::Templates::Engine.register_template_path(File.dirname(__FILE__) + '/../../templates')
2
+ require File.join(File.dirname(__FILE__), 'handler') if RUBY19
@@ -2,8 +2,16 @@ require 'spec_helper'
2
2
  require 'hutch/broker'
3
3
 
4
4
  describe Hutch::Broker do
5
- let(:config) { deep_copy(Hutch::Config.user_config) }
6
- subject(:broker) { Hutch::Broker.new(config) }
5
+ before do
6
+ Hutch::Config.initialize(client_logger: Hutch::Logging.logger)
7
+ @config = Hutch::Config.to_hash
8
+ end
9
+ let!(:config) { @config }
10
+ after do
11
+ Hutch::Config.instance_variable_set(:@config, nil)
12
+ Hutch::Config.initialize
13
+ end
14
+ let(:broker) { Hutch::Broker.new(config) }
7
15
 
8
16
  describe '#connect' do
9
17
  before { allow(broker).to receive(:set_up_amqp_connection) }
@@ -53,93 +61,183 @@ describe Hutch::Broker do
53
61
  end
54
62
  end
55
63
 
56
- describe '#set_up_amqp_connection', rabbitmq: true do
57
- context 'with valid details' do
58
- before { broker.set_up_amqp_connection }
59
- after { broker.disconnect }
64
+ describe '#set_up_amqp_connection' do
65
+ it 'opens a connection, channel and declares an exchange' do
66
+ expect(broker).to receive(:open_connection!).ordered
67
+ expect(broker).to receive(:open_channel!).ordered
68
+ expect(broker).to receive(:declare_exchange!).ordered
60
69
 
61
- describe '#connection', adapter: :bunny do
62
- subject { super().connection }
63
- it { is_expected.to be_a Hutch::Adapters::BunnyAdapter }
64
- end
70
+ broker.set_up_amqp_connection
71
+ end
72
+ end
65
73
 
66
- describe '#connection', adapter: :march_hare do
67
- subject { super().connection }
68
- it { is_expected.to be_a Hutch::Adapters::MarchHareAdapter }
69
- end
74
+ describe '#open_connection', rabbitmq: true do
75
+ describe 'return value' do
76
+ subject { broker.open_connection }
77
+ after { subject.close }
70
78
 
71
- describe '#channel', adapter: :bunny do
72
- subject { super().channel }
73
- it { is_expected.to be_a Bunny::Channel }
74
- end
79
+ it(nil, adapter: :bunny) { is_expected.to be_a Hutch::Adapters::BunnyAdapter }
80
+ it(nil, adapter: :march_hare) { is_expected.to be_a Hutch::Adapters::MarchHareAdapter }
81
+ end
75
82
 
76
- describe '#channel', adapter: :march_hare do
77
- subject { super().channel }
78
- it { is_expected.to be_a MarchHare::Channel }
83
+ context 'when given invalid details' do
84
+ before { config[:mq_host] = 'notarealhost' }
85
+ it { expect { broker.open_connection }.to raise_error(StandardError) }
86
+ end
87
+
88
+ it 'does not set #connection' do
89
+ connection = broker.open_connection
90
+
91
+ expect(broker.connection).to be_nil
92
+
93
+ connection.close
94
+ end
95
+
96
+ context 'when configured with a URI' do
97
+ context 'which specifies the port' do
98
+ before { config[:uri] = 'amqp://guest:guest@127.0.0.1:5672/' }
99
+
100
+ it 'successfully connects' do
101
+ c = broker.open_connection
102
+ expect(c).to be_open
103
+ c.close
104
+ end
79
105
  end
80
106
 
81
- describe '#exchange', adapter: :bunny do
82
- subject { super().exchange }
83
- it { is_expected.to be_a Bunny::Exchange }
107
+ context 'which does not specify port and uses the amqp scheme' do
108
+ before { config[:uri] = 'amqp://guest:guest@127.0.0.1/' }
109
+
110
+ it 'successfully connects' do
111
+ c = broker.open_connection
112
+ expect(c).to be_open
113
+ c.close
114
+ end
84
115
  end
85
116
 
86
- describe '#exchange', adapter: :march_hare do
87
- subject { super().exchange }
88
- it { is_expected.to be_a MarchHare::Exchange }
117
+ context 'which specifies the amqps scheme' do
118
+ before { config[:uri] = 'amqps://guest:guest@127.0.0.1/' }
119
+
120
+ it 'utilises TLS' do
121
+ expect(Hutch::Adapter).to receive(:new).with(
122
+ hash_including(tls: true, port: 5671)
123
+ ).and_return(instance_double('Hutch::Adapter', start: nil))
124
+
125
+ broker.open_connection
126
+ end
89
127
  end
90
128
  end
129
+ end
91
130
 
92
- context 'when given invalid details' do
93
- before { config[:mq_host] = 'notarealhost' }
94
- let(:set_up_amqp_connection) { ->{ broker.set_up_amqp_connection } }
131
+ describe '#open_connection!' do
132
+ it 'sets the #connection to #open_connection' do
133
+ connection = double('connection').as_null_object
134
+
135
+ expect(broker).to receive(:open_connection).and_return(connection)
136
+
137
+ broker.open_connection!
95
138
 
96
- specify { expect(set_up_amqp_connection).to raise_error }
139
+ expect(broker.connection).to eq(connection)
140
+ end
141
+ end
142
+
143
+ describe '#open_channel', rabbitmq: true do
144
+ before { broker.open_connection! }
145
+ after { broker.disconnect }
146
+
147
+ describe 'return value' do
148
+ subject { broker.open_channel }
149
+
150
+ it(nil, adapter: :bunny) { is_expected.to be_a Bunny::Channel }
151
+ it(nil, adapter: :march_hare) { is_expected.to be_a MarchHare::Channel }
152
+ end
153
+
154
+ it 'does not set #channel' do
155
+ broker.open_channel
156
+ expect(broker.channel).to be_nil
97
157
  end
98
158
 
99
159
  context 'with channel_prefetch set' do
100
160
  let(:prefetch_value) { 1 }
101
161
  before { config[:channel_prefetch] = prefetch_value }
102
- after { broker.disconnect }
103
162
 
104
163
  it "set's channel's prefetch", adapter: :bunny do
105
- expect_any_instance_of(Bunny::Channel).
106
- to receive(:prefetch).with(prefetch_value)
107
- broker.set_up_amqp_connection
164
+ expect_any_instance_of(Bunny::Channel).to receive(:prefetch).with(prefetch_value)
165
+ broker.open_channel
108
166
  end
109
167
 
110
168
  it "set's channel's prefetch", adapter: :march_hare do
111
- expect_any_instance_of(MarchHare::Channel).
112
- to receive(:prefetch=).with(prefetch_value)
113
- broker.set_up_amqp_connection
169
+ expect_any_instance_of(MarchHare::Channel).to receive(:prefetch=).with(prefetch_value)
170
+ broker.open_channel
114
171
  end
115
172
  end
116
173
 
117
174
  context 'with force_publisher_confirms set' do
118
175
  let(:force_publisher_confirms_value) { true }
119
176
  before { config[:force_publisher_confirms] = force_publisher_confirms_value }
120
- after { broker.disconnect }
121
177
 
122
178
  it 'waits for confirmation', adapter: :bunny do
123
- expect_any_instance_of(Bunny::Channel).
124
- to receive(:confirm_select)
125
- broker.set_up_amqp_connection
179
+ expect_any_instance_of(Bunny::Channel).to receive(:confirm_select)
180
+ broker.open_channel
126
181
  end
127
182
 
128
183
  it 'waits for confirmation', adapter: :march_hare do
129
- expect_any_instance_of(MarchHare::Channel).
130
- to receive(:confirm_select)
131
- broker.set_up_amqp_connection
184
+ expect_any_instance_of(MarchHare::Channel).to receive(:confirm_select)
185
+ broker.open_channel
132
186
  end
133
187
  end
134
188
  end
135
189
 
190
+ describe '#open_channel!' do
191
+ it 'sets the #channel to #open_channel' do
192
+ channel = double('channel').as_null_object
193
+
194
+ expect(broker).to receive(:open_channel).and_return(channel)
195
+
196
+ broker.open_channel!
197
+
198
+ expect(broker.channel).to eq(channel)
199
+ end
200
+ end
201
+
202
+ describe '#declare_exchange' do
203
+ before do
204
+ broker.open_connection!
205
+ broker.open_channel!
206
+ end
207
+ after { broker.disconnect }
208
+
209
+ describe 'return value' do
210
+ subject { broker.declare_exchange }
211
+
212
+ it(nil, adapter: :bunny) { is_expected.to be_a Bunny::Exchange }
213
+ it(nil, adapter: :march_hare) { is_expected.to be_a MarchHare::Exchange }
214
+ end
215
+
216
+ it 'does not set #exchange' do
217
+ broker.declare_exchange
218
+ expect(broker.exchange).to be_nil
219
+ end
220
+ end
221
+
222
+ describe '#declare_exchange!' do
223
+ it 'sets the #exchange to #declare_exchange' do
224
+ exchange = double('exchange').as_null_object
225
+
226
+ expect(broker).to receive(:declare_exchange).and_return(exchange)
227
+
228
+ broker.declare_exchange!
229
+
230
+ expect(broker.exchange).to eq(exchange)
231
+ end
232
+ end
233
+
136
234
  describe '#set_up_api_connection', rabbitmq: true do
137
235
  context 'with valid details' do
138
236
  before { broker.set_up_api_connection }
139
237
  after { broker.disconnect }
140
238
 
141
239
  describe '#api_client' do
142
- subject { super().api_client }
240
+ subject { broker.api_client }
143
241
  it { is_expected.to be_a CarrotTop }
144
242
  end
145
243
  end
@@ -149,7 +247,7 @@ describe Hutch::Broker do
149
247
  after { broker.disconnect }
150
248
  let(:set_up_api_connection) { ->{ broker.set_up_api_connection } }
151
249
 
152
- specify { expect(set_up_api_connection).to raise_error }
250
+ specify { expect(set_up_api_connection).to raise_error(StandardError) }
153
251
  end
154
252
  end
155
253
 
@@ -192,7 +290,7 @@ describe Hutch::Broker do
192
290
 
193
291
  describe '#bind_queue' do
194
292
 
195
- around { |example| broker.connect { example.run } }
293
+ around { |example| broker.connect(host: "127.0.0.1") { example.run } }
196
294
 
197
295
  let(:routing_keys) { %w( a b c ) }
198
296
  let(:queue) { double('Queue', bind: nil, unbind: nil, name: 'consumer') }
@@ -225,21 +323,6 @@ describe Hutch::Broker do
225
323
  end
226
324
  end
227
325
 
228
- describe '#wait_on_threads' do
229
- let(:thread) { double('Thread') }
230
- before { allow(broker).to receive(:work_pool_threads).and_return(threads) }
231
-
232
- context 'when all threads finish within the timeout' do
233
- let(:threads) { [double(join: thread), double(join: thread)] }
234
- specify { expect(broker.wait_on_threads(1)).to be_truthy }
235
- end
236
-
237
- context 'when timeout expires for one thread' do
238
- let(:threads) { [double(join: thread), double(join: nil)] }
239
- specify { expect(broker.wait_on_threads(1)).to be_falsey }
240
- end
241
- end
242
-
243
326
  describe '#stop', adapter: :bunny do
244
327
  let(:thread_1) { double('Thread') }
245
328
  let(:thread_2) { double('Thread') }
@@ -280,12 +363,12 @@ describe Hutch::Broker do
280
363
 
281
364
  it 'publishes to the exchange' do
282
365
  expect(broker.exchange).to receive(:publish).once
283
- broker.publish('test.key', 'message')
366
+ broker.publish('test.key', {key: "value"})
284
367
  end
285
368
 
286
369
  it 'sets default properties' do
287
370
  expect(broker.exchange).to receive(:publish).with(
288
- JSON.dump("message"),
371
+ JSON.dump({key: "value"}),
289
372
  hash_including(
290
373
  persistent: true,
291
374
  routing_key: 'test.key',
@@ -293,12 +376,12 @@ describe Hutch::Broker do
293
376
  )
294
377
  )
295
378
 
296
- broker.publish('test.key', 'message')
379
+ broker.publish('test.key', {key: "value"})
297
380
  end
298
381
 
299
382
  it 'allows passing message properties' do
300
383
  expect(broker.exchange).to receive(:publish).once
301
- broker.publish('test.key', 'message', {expiration: "2000", persistent: false})
384
+ broker.publish('test.key', {key: "value"}, {expiration: "2000", persistent: false})
302
385
  end
303
386
 
304
387
  context 'when there are global properties' do
@@ -309,8 +392,8 @@ describe Hutch::Broker do
309
392
 
310
393
  it 'merges the properties' do
311
394
  expect(broker.exchange).
312
- to receive(:publish).with('"message"', hash_including(app_id: 'app'))
313
- broker.publish('test.key', 'message')
395
+ to receive(:publish).with('{"key":"value"}', hash_including(app_id: 'app'))
396
+ broker.publish('test.key', {key: "value"})
314
397
  end
315
398
  end
316
399
 
@@ -321,8 +404,8 @@ describe Hutch::Broker do
321
404
 
322
405
  it 'calls the proc and merges the properties' do
323
406
  expect(broker.exchange).
324
- to receive(:publish).with('"message"', hash_including(app_id: 'app'))
325
- broker.publish('test.key', 'message')
407
+ to receive(:publish).with('{"key":"value"}', hash_including(app_id: 'app'))
408
+ broker.publish('test.key', {key: "value"})
326
409
  end
327
410
  end
328
411
  end
@@ -331,13 +414,13 @@ describe Hutch::Broker do
331
414
  it 'does not wait for confirms on the channel', adapter: :bunny do
332
415
  expect_any_instance_of(Bunny::Channel).
333
416
  to_not receive(:wait_for_confirms)
334
- broker.publish('test.key', 'message')
417
+ broker.publish('test.key', {key: "value"})
335
418
  end
336
419
 
337
420
  it 'does not wait for confirms on the channel', adapter: :march_hare do
338
421
  expect_any_instance_of(MarchHare::Channel).
339
422
  to_not receive(:wait_for_confirms)
340
- broker.publish('test.key', 'message')
423
+ broker.publish('test.key', {key: "value"})
341
424
  end
342
425
  end
343
426
 
@@ -351,26 +434,28 @@ describe Hutch::Broker do
351
434
  it 'waits for confirms on the channel', adapter: :bunny do
352
435
  expect_any_instance_of(Bunny::Channel).
353
436
  to receive(:wait_for_confirms)
354
- broker.publish('test.key', 'message')
437
+ broker.publish('test.key', {key: "value"})
355
438
  end
356
439
 
357
440
  it 'waits for confirms on the channel', adapter: :march_hare do
358
441
  expect_any_instance_of(MarchHare::Channel).
359
442
  to receive(:wait_for_confirms)
360
- broker.publish('test.key', 'message')
443
+ broker.publish('test.key', {key: "value"})
361
444
  end
362
445
  end
363
446
  end
364
447
 
365
448
  context 'without a valid connection' do
449
+ before { broker.set_up_amqp_connection; broker.disconnect }
450
+
366
451
  it 'raises an exception' do
367
- expect { broker.publish('test.key', 'message') }.
452
+ expect { broker.publish('test.key', {key: "value"}) }.
368
453
  to raise_exception(Hutch::PublishError)
369
454
  end
370
455
 
371
456
  it 'logs an error' do
372
457
  expect(broker.logger).to receive(:error)
373
- broker.publish('test.key', 'message') rescue nil
458
+ broker.publish('test.key', {key: "value"}) rescue nil
374
459
  end
375
460
  end
376
461
  end