amq-client 0.7.0.alpha35 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.rspec +0 -1
- data/.travis.yml +9 -3
- data/Gemfile +22 -12
- data/amq-client.gemspec +1 -1
- data/examples/coolio_adapter/example_helper.rb +2 -0
- data/examples/eventmachine_adapter/basic_consume_with_acknowledgements.rb +3 -3
- data/examples/eventmachine_adapter/{connection_failure_callback.rb → error_handling/connection_failure_callback.rb} +4 -8
- data/examples/eventmachine_adapter/{connection_failure_exception.rb → error_handling/connection_failure_exception.rb} +5 -9
- data/examples/eventmachine_adapter/{connection_loss_handler.rb → error_handling/connection_loss_handler_that_fails_over.rb} +12 -12
- data/examples/eventmachine_adapter/error_handling/connection_loss_handler_with_automatic_recovery.rb +85 -0
- data/examples/eventmachine_adapter/error_handling/connection_loss_handler_with_manual_recovery.rb +85 -0
- data/examples/eventmachine_adapter/error_handling/handling_a_channel_level_exception.rb +2 -5
- data/examples/eventmachine_adapter/example_helper.rb +2 -0
- data/examples/eventmachine_adapter/server_capabilities.rb +12 -0
- data/examples/eventmachine_adapter/tls/tls_without_peer_verification.rb +2 -2
- data/lib/amq/client/async/adapter.rb +170 -31
- data/lib/amq/client/async/adapters/coolio.rb +18 -1
- data/lib/amq/client/async/adapters/event_machine.rb +48 -32
- data/lib/amq/client/async/adapters/eventmachine.rb +3 -1
- data/lib/amq/client/async/callbacks.rb +9 -7
- data/lib/amq/client/async/channel.rb +113 -20
- data/lib/amq/client/async/consumer.rb +270 -0
- data/lib/amq/client/async/exchange.rb +137 -16
- data/lib/amq/client/async/extensions/rabbitmq/confirm.rb +4 -4
- data/lib/amq/client/async/queue.rb +217 -113
- data/lib/amq/client/callbacks.rb +2 -0
- data/lib/amq/client/consumer_tag_generator.rb +24 -0
- data/lib/amq/client/exceptions.rb +10 -6
- data/lib/amq/client/handlers_registry.rb +2 -0
- data/lib/amq/client/queue.rb +2 -0
- data/lib/amq/client/server_named_entity.rb +1 -8
- data/lib/amq/client/settings.rb +64 -2
- data/lib/amq/client/version.rb +3 -1
- data/spec/benchmarks/adapters.rb +2 -0
- data/spec/client/framing/io_frame_spec.rb +9 -6
- data/spec/integration/coolio/basic_ack_spec.rb +2 -0
- data/spec/integration/coolio/basic_cancel_spec.rb +2 -0
- data/spec/integration/coolio/basic_consume_spec.rb +58 -0
- data/spec/integration/coolio/basic_get_spec.rb +2 -0
- data/spec/integration/coolio/basic_return_spec.rb +2 -0
- data/spec/integration/coolio/channel_close_spec.rb +2 -0
- data/spec/integration/coolio/channel_flow_spec.rb +2 -0
- data/spec/integration/coolio/connection_close_spec.rb +2 -0
- data/spec/integration/coolio/connection_start_spec.rb +2 -0
- data/spec/integration/coolio/exchange_declare_spec.rb +8 -6
- data/spec/integration/coolio/spec_helper.rb +2 -0
- data/spec/integration/coolio/tx_commit_spec.rb +2 -1
- data/spec/integration/coolio/tx_rollback_spec.rb +1 -1
- data/spec/integration/eventmachine/basic_ack_spec.rb +3 -1
- data/spec/integration/eventmachine/basic_cancel_spec.rb +2 -0
- data/spec/integration/eventmachine/basic_consume_spec.rb +90 -6
- data/spec/integration/eventmachine/basic_get_spec.rb +2 -0
- data/spec/integration/eventmachine/basic_return_spec.rb +2 -0
- data/spec/integration/eventmachine/channel_close_spec.rb +2 -0
- data/spec/integration/eventmachine/channel_flow_spec.rb +4 -2
- data/spec/integration/eventmachine/concurrent_basic_publish_spec.rb +79 -0
- data/spec/integration/eventmachine/connection_close_spec.rb +2 -0
- data/spec/integration/eventmachine/connection_start_spec.rb +2 -0
- data/spec/integration/eventmachine/exchange_declare_spec.rb +4 -2
- data/spec/integration/eventmachine/queue_declare_spec.rb +2 -0
- data/spec/integration/eventmachine/regressions/amqp_gem_issue66_spec.rb +2 -0
- data/spec/integration/eventmachine/spec_helper.rb +2 -0
- data/spec/integration/eventmachine/tx_commit_spec.rb +2 -1
- data/spec/integration/eventmachine/tx_rollback_spec.rb +1 -1
- data/spec/regression/bad_frame_slicing_in_adapters_spec.rb +2 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/unit/client/settings_spec.rb +92 -3
- metadata +24 -23
- data/CONTRIBUTORS +0 -3
@@ -1,3 +1,5 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module AMQ
|
2
4
|
module Client
|
3
5
|
module Async
|
@@ -34,28 +36,28 @@ module AMQ
|
|
34
36
|
|
35
37
|
|
36
38
|
def exec_callback(name, *args, &block)
|
37
|
-
list = Array(
|
39
|
+
list = Array(@callbacks[name])
|
38
40
|
if list.any?
|
39
41
|
list.each { |c| c.call(*args, &block) }
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
def exec_callback_once(name, *args, &block)
|
44
|
-
list = (
|
46
|
+
list = (@callbacks.delete(name) || Array.new)
|
45
47
|
if list.any?
|
46
48
|
list.each { |c| c.call(*args, &block) }
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
52
|
def exec_callback_yielding_self(name, *args, &block)
|
51
|
-
list = Array(
|
53
|
+
list = Array(@callbacks[name])
|
52
54
|
if list.any?
|
53
55
|
list.each { |c| c.call(self, *args, &block) }
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
57
59
|
def exec_callback_once_yielding_self(name, *args, &block)
|
58
|
-
list = (
|
60
|
+
list = (@callbacks.delete(name) || Array.new)
|
59
61
|
|
60
62
|
if list.any?
|
61
63
|
list.each { |c| c.call(self, *args, &block) }
|
@@ -63,9 +65,9 @@ module AMQ
|
|
63
65
|
end
|
64
66
|
|
65
67
|
def has_callback?(name)
|
66
|
-
|
68
|
+
@callbacks[name] && !@callbacks[name].empty?
|
67
69
|
end # has_callback?
|
68
|
-
end # Callbacks
|
70
|
+
end # Callbacks
|
69
71
|
end # Async
|
70
72
|
end # Client
|
71
|
-
end # AMQ
|
73
|
+
end # AMQ
|
@@ -25,30 +25,29 @@ module AMQ
|
|
25
25
|
#
|
26
26
|
|
27
27
|
|
28
|
-
class ChannelOutOfBadError < StandardError # TODO: inherit from some AMQP error class defined in amq-protocol or use it straight away.
|
29
|
-
def initialize(max, given)
|
30
|
-
super("Channel max is #{max}, #{given} given.")
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
28
|
DEFAULT_REPLY_TEXT = "Goodbye".freeze
|
36
29
|
|
37
30
|
attr_reader :id
|
38
31
|
|
39
32
|
attr_reader :exchanges_awaiting_declare_ok, :exchanges_awaiting_delete_ok
|
40
|
-
attr_reader :queues_awaiting_declare_ok, :queues_awaiting_delete_ok, :queues_awaiting_bind_ok, :queues_awaiting_unbind_ok, :queues_awaiting_purge_ok, :
|
33
|
+
attr_reader :queues_awaiting_declare_ok, :queues_awaiting_delete_ok, :queues_awaiting_bind_ok, :queues_awaiting_unbind_ok, :queues_awaiting_purge_ok, :queues_awaiting_get_response
|
34
|
+
attr_reader :consumers_awaiting_consume_ok, :consumers_awaiting_cancel_ok
|
41
35
|
|
42
36
|
attr_accessor :flow_is_active
|
43
37
|
|
44
38
|
|
45
|
-
def initialize(connection, id)
|
39
|
+
def initialize(connection, id, options = {})
|
46
40
|
super(connection)
|
47
41
|
|
48
42
|
@id = id
|
49
43
|
@exchanges = Hash.new
|
50
44
|
@queues = Hash.new
|
51
45
|
@consumers = Hash.new
|
46
|
+
@options = { :auto_recovery => connection.auto_recovering? }.merge(options)
|
47
|
+
@auto_recovery = (!!@options[:auto_recovery])
|
48
|
+
|
49
|
+
# we must synchronize frameset delivery. MK.
|
50
|
+
@mutex = Mutex.new
|
52
51
|
|
53
52
|
reset_state!
|
54
53
|
|
@@ -62,10 +61,17 @@ module AMQ
|
|
62
61
|
end
|
63
62
|
|
64
63
|
if channel_max != 0 && !(0..channel_max).include?(id)
|
65
|
-
raise
|
64
|
+
raise ArgumentError.new("Max channel for the connection is #{channel_max}, given: #{id}")
|
66
65
|
end
|
67
66
|
end
|
68
67
|
|
68
|
+
# @return [Boolean] true if this channel uses automatic recovery mode
|
69
|
+
def auto_recovering?
|
70
|
+
@auto_recovery
|
71
|
+
end # auto_recovering?
|
72
|
+
|
73
|
+
|
74
|
+
# @return [Hash<String, Consumer>]
|
69
75
|
def consumers
|
70
76
|
@consumers
|
71
77
|
end # consumers
|
@@ -88,6 +94,12 @@ module AMQ
|
|
88
94
|
@connection
|
89
95
|
end # connection
|
90
96
|
|
97
|
+
# Synchronizes given block using this channel's mutex.
|
98
|
+
# @api public
|
99
|
+
def synchronize(&block)
|
100
|
+
@mutex.synchronize(&block)
|
101
|
+
end
|
102
|
+
|
91
103
|
|
92
104
|
# @group Channel lifecycle
|
93
105
|
|
@@ -101,6 +113,7 @@ module AMQ
|
|
101
113
|
|
102
114
|
self.redefine_callback :open, &block
|
103
115
|
end
|
116
|
+
alias reopen open
|
104
117
|
|
105
118
|
# Closes AMQP channel.
|
106
119
|
#
|
@@ -245,6 +258,77 @@ module AMQ
|
|
245
258
|
self.define_callback(:error, &block)
|
246
259
|
end
|
247
260
|
|
261
|
+
|
262
|
+
# Defines a callback that will be executed after TCP connection is interrupted (typically because of a network failure).
|
263
|
+
# Only one callback can be defined (the one defined last replaces previously added ones).
|
264
|
+
#
|
265
|
+
# @api public
|
266
|
+
def on_connection_interruption(&block)
|
267
|
+
self.redefine_callback(:after_connection_interruption, &block)
|
268
|
+
end # on_connection_interruption(&block)
|
269
|
+
alias after_connection_interruption on_connection_interruption
|
270
|
+
|
271
|
+
# @private
|
272
|
+
def handle_connection_interruption(method = nil)
|
273
|
+
@queues.each { |name, q| q.handle_connection_interruption(method) }
|
274
|
+
@exchanges.each { |name, e| e.handle_connection_interruption(method) }
|
275
|
+
|
276
|
+
self.exec_callback_yielding_self(:after_connection_interruption)
|
277
|
+
self.reset_state!
|
278
|
+
end # handle_connection_interruption
|
279
|
+
|
280
|
+
|
281
|
+
# Defines a callback that will be executed after TCP connection has recovered after a network failure
|
282
|
+
# but before AMQP connection is re-opened.
|
283
|
+
# Only one callback can be defined (the one defined last replaces previously added ones).
|
284
|
+
#
|
285
|
+
# @api public
|
286
|
+
def before_recovery(&block)
|
287
|
+
self.redefine_callback(:before_recovery, &block)
|
288
|
+
end # before_recovery(&block)
|
289
|
+
|
290
|
+
# @private
|
291
|
+
def run_before_recovery_callbacks
|
292
|
+
self.exec_callback_yielding_self(:before_recovery)
|
293
|
+
|
294
|
+
@queues.each { |name, q| q.run_before_recovery_callbacks }
|
295
|
+
@exchanges.each { |name, e| e.run_before_recovery_callbacks }
|
296
|
+
end
|
297
|
+
|
298
|
+
|
299
|
+
|
300
|
+
# Defines a callback that will be executed after AMQP connection has recovered after a network failure.
|
301
|
+
# Only one callback can be defined (the one defined last replaces previously added ones).
|
302
|
+
#
|
303
|
+
# @api public
|
304
|
+
def on_recovery(&block)
|
305
|
+
self.redefine_callback(:after_recovery, &block)
|
306
|
+
end # on_recovery(&block)
|
307
|
+
alias after_recovery on_recovery
|
308
|
+
|
309
|
+
# @private
|
310
|
+
def run_after_recovery_callbacks
|
311
|
+
self.exec_callback_yielding_self(:after_recovery)
|
312
|
+
|
313
|
+
@queues.each { |name, q| q.run_after_recovery_callbacks }
|
314
|
+
@exchanges.each { |name, e| e.run_after_recovery_callbacks }
|
315
|
+
end
|
316
|
+
|
317
|
+
|
318
|
+
# Called by associated connection object when AMQP connection has been re-established
|
319
|
+
# (for example, after a network failure).
|
320
|
+
#
|
321
|
+
# @api plugin
|
322
|
+
def auto_recover
|
323
|
+
return unless auto_recovering?
|
324
|
+
|
325
|
+
self.open do
|
326
|
+
# exchanges must be recovered first because queue recovery includes recovery of bindings. MK.
|
327
|
+
@exchanges.each { |name, e| e.auto_recover }
|
328
|
+
@queues.each { |name, q| q.auto_recover }
|
329
|
+
end
|
330
|
+
end # auto_recover
|
331
|
+
|
248
332
|
# @endgroup
|
249
333
|
|
250
334
|
|
@@ -268,17 +352,26 @@ module AMQ
|
|
268
352
|
@exchanges[name]
|
269
353
|
end
|
270
354
|
|
355
|
+
# @api plugin
|
356
|
+
# @private
|
271
357
|
def register_queue(queue)
|
272
358
|
raise ArgumentError, "argument is nil!" if queue.nil?
|
273
359
|
|
274
360
|
@queues[queue.name] = queue
|
275
361
|
end # register_queue(queue)
|
276
362
|
|
363
|
+
# @api plugin
|
364
|
+
# @private
|
277
365
|
def find_queue(name)
|
278
366
|
@queues[name]
|
279
367
|
end
|
280
368
|
|
281
369
|
|
370
|
+
RECOVERY_EVENTS = [:after_connection_interruption, :before_recovery, :after_recovery].freeze
|
371
|
+
|
372
|
+
|
373
|
+
# @api plugin
|
374
|
+
# @private
|
282
375
|
def reset_state!
|
283
376
|
@flow_is_active = true
|
284
377
|
|
@@ -291,31 +384,31 @@ module AMQ
|
|
291
384
|
@queues_awaiting_purge_ok = Array.new
|
292
385
|
@queues_awaiting_bind_ok = Array.new
|
293
386
|
@queues_awaiting_unbind_ok = Array.new
|
294
|
-
@
|
295
|
-
@
|
387
|
+
@consumers_awaiting_consume_ok = Array.new
|
388
|
+
@consumers_awaiting_cancel_ok = Array.new
|
296
389
|
|
297
390
|
@queues_awaiting_get_response = Array.new
|
298
391
|
|
299
|
-
@callbacks =
|
392
|
+
@callbacks = @callbacks.delete_if { |k, v| !RECOVERY_EVENTS.include?(k) }
|
300
393
|
end # reset_state!
|
301
394
|
|
302
395
|
|
303
|
-
|
304
|
-
|
305
|
-
end # handle_connection_interruption
|
306
|
-
|
307
|
-
|
308
|
-
|
396
|
+
# @api plugin
|
397
|
+
# @private
|
309
398
|
def handle_open_ok(open_ok)
|
310
399
|
self.status = :opened
|
311
400
|
self.exec_callback_once_yielding_self(:open, open_ok)
|
312
401
|
end
|
313
402
|
|
403
|
+
# @api plugin
|
404
|
+
# @private
|
314
405
|
def handle_close_ok(close_ok)
|
315
406
|
self.status = :closed
|
316
407
|
self.exec_callback_once_yielding_self(:close, close_ok)
|
317
408
|
end
|
318
409
|
|
410
|
+
# @api plugin
|
411
|
+
# @private
|
319
412
|
def handle_close(channel_close)
|
320
413
|
self.status = :closed
|
321
414
|
self.exec_callback_yielding_self(:error, channel_close)
|
@@ -379,7 +472,7 @@ module AMQ
|
|
379
472
|
channel = connection.channels[frame.channel]
|
380
473
|
channel.exec_callback(:tx_rollback, frame.decode_payload)
|
381
474
|
end
|
382
|
-
end # Channel
|
475
|
+
end # Channel
|
383
476
|
end # Async
|
384
477
|
end # Client
|
385
478
|
end # AMQ
|
@@ -0,0 +1,270 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "amq/client/async/callbacks"
|
4
|
+
require "amq/client/consumer_tag_generator"
|
5
|
+
|
6
|
+
module AMQ
|
7
|
+
module Client
|
8
|
+
module Async
|
9
|
+
class Consumer
|
10
|
+
|
11
|
+
#
|
12
|
+
# Behaviors
|
13
|
+
#
|
14
|
+
|
15
|
+
include Async::Callbacks
|
16
|
+
extend Async::ProtocolMethodHandlers
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
#
|
21
|
+
# API
|
22
|
+
#
|
23
|
+
|
24
|
+
attr_reader :channel
|
25
|
+
attr_reader :queue
|
26
|
+
attr_reader :consumer_tag
|
27
|
+
attr_reader :arguments
|
28
|
+
|
29
|
+
|
30
|
+
def self.tag_generator
|
31
|
+
@tag_generator ||= AMQ::Client::ConsumerTagGenerator.new
|
32
|
+
end # self.tag_generator
|
33
|
+
|
34
|
+
def self.tag_generator=(generator)
|
35
|
+
@tag_generator = generator
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
def initialize(channel, queue, consumer_tag = self.class.tag_generator.generate_for(queue), exclusive = false, no_ack = false, arguments = {}, no_local = false, &block)
|
40
|
+
@callbacks = Hash.new
|
41
|
+
|
42
|
+
@channel = channel || raise(ArgumentError, "channel is nil")
|
43
|
+
@connection = channel.connection || raise(ArgumentError, "connection is nil")
|
44
|
+
@queue = queue || raise(ArgumentError, "queue is nil")
|
45
|
+
@consumer_tag = consumer_tag
|
46
|
+
@exclusive = exclusive
|
47
|
+
@no_ack = no_ack
|
48
|
+
@arguments = arguments
|
49
|
+
|
50
|
+
@no_local = no_local
|
51
|
+
|
52
|
+
self.register_with_channel
|
53
|
+
self.register_with_queue
|
54
|
+
end # initialize
|
55
|
+
|
56
|
+
|
57
|
+
def exclusive?
|
58
|
+
!!@exclusive
|
59
|
+
end # exclusive?
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
def consume(nowait = false, &block)
|
64
|
+
@connection.send_frame(Protocol::Basic::Consume.encode(@channel.id, @queue.name, @consumer_tag, @no_local, @no_ack, @exclusive, nowait, @arguments))
|
65
|
+
self.redefine_callback(:consume, &block)
|
66
|
+
|
67
|
+
@channel.consumers_awaiting_consume_ok.push(self)
|
68
|
+
|
69
|
+
self
|
70
|
+
end # consume(nowait = false, &block)
|
71
|
+
|
72
|
+
# Used by automatic recovery code.
|
73
|
+
# @api plugin
|
74
|
+
def resubscribe(&block)
|
75
|
+
@connection.send_frame(Protocol::Basic::Consume.encode(@channel.id, @queue.name, @consumer_tag, @no_local, @no_ack, @exclusive, block.nil?, @arguments))
|
76
|
+
self.redefine_callback(:consume, &block) if block
|
77
|
+
|
78
|
+
self
|
79
|
+
end # resubscribe(&block)
|
80
|
+
|
81
|
+
|
82
|
+
def cancel(nowait = false, &block)
|
83
|
+
@connection.send_frame(Protocol::Basic::Cancel.encode(@channel.id, @consumer_tag, nowait))
|
84
|
+
self.clear_callbacks(:delivery)
|
85
|
+
self.clear_callbacks(:consume)
|
86
|
+
|
87
|
+
self.unregister_with_channel
|
88
|
+
self.unregister_with_queue
|
89
|
+
|
90
|
+
if !nowait
|
91
|
+
self.redefine_callback(:cancel, &block)
|
92
|
+
@channel.consumers_awaiting_cancel_ok.push(self)
|
93
|
+
end
|
94
|
+
|
95
|
+
self
|
96
|
+
end # cancel(nowait = false, &block)
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
def on_delivery(&block)
|
101
|
+
self.append_callback(:delivery, &block)
|
102
|
+
|
103
|
+
self
|
104
|
+
end # on_delivery(&block)
|
105
|
+
|
106
|
+
|
107
|
+
# @group Acknowledging & Rejecting Messages
|
108
|
+
|
109
|
+
# Acknowledge a delivery tag.
|
110
|
+
# @return [Consumer] self
|
111
|
+
#
|
112
|
+
# @api public
|
113
|
+
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.13.)
|
114
|
+
def acknowledge(delivery_tag)
|
115
|
+
@channel.acknowledge(delivery_tag)
|
116
|
+
|
117
|
+
self
|
118
|
+
end # acknowledge(delivery_tag)
|
119
|
+
|
120
|
+
#
|
121
|
+
# @return [Consumer] self
|
122
|
+
#
|
123
|
+
# @api public
|
124
|
+
# @see http://bit.ly/htCzCX AMQP 0.9.1 protocol documentation (Section 1.8.3.14.)
|
125
|
+
def reject(delivery_tag, requeue = true)
|
126
|
+
@channel.reject(delivery_tag, requeue)
|
127
|
+
|
128
|
+
self
|
129
|
+
end # reject(delivery_tag, requeue = true)
|
130
|
+
|
131
|
+
# @endgroup
|
132
|
+
|
133
|
+
|
134
|
+
# @group Error Handling & Recovery
|
135
|
+
|
136
|
+
# Defines a callback that will be executed after TCP connection is interrupted (typically because of a network failure).
|
137
|
+
# Only one callback can be defined (the one defined last replaces previously added ones).
|
138
|
+
#
|
139
|
+
# @api public
|
140
|
+
def on_connection_interruption(&block)
|
141
|
+
self.redefine_callback(:after_connection_interruption, &block)
|
142
|
+
end # on_connection_interruption(&block)
|
143
|
+
alias after_connection_interruption on_connection_interruption
|
144
|
+
|
145
|
+
# @private
|
146
|
+
def handle_connection_interruption(method = nil)
|
147
|
+
self.exec_callback_yielding_self(:after_connection_interruption)
|
148
|
+
end # handle_connection_interruption
|
149
|
+
|
150
|
+
|
151
|
+
# Defines a callback that will be executed after TCP connection is recovered after a network failure
|
152
|
+
# but before AMQP connection is re-opened.
|
153
|
+
# Only one callback can be defined (the one defined last replaces previously added ones).
|
154
|
+
#
|
155
|
+
# @api public
|
156
|
+
def before_recovery(&block)
|
157
|
+
self.redefine_callback(:before_recovery, &block)
|
158
|
+
end # before_recovery(&block)
|
159
|
+
|
160
|
+
# @private
|
161
|
+
def run_before_recovery_callbacks
|
162
|
+
self.exec_callback_yielding_self(:before_recovery)
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
# Defines a callback that will be executed when AMQP connection is recovered after a network failure..
|
167
|
+
# Only one callback can be defined (the one defined last replaces previously added ones).
|
168
|
+
#
|
169
|
+
# @api public
|
170
|
+
def on_recovery(&block)
|
171
|
+
self.redefine_callback(:after_recovery, &block)
|
172
|
+
end # on_recovery(&block)
|
173
|
+
alias after_recovery on_recovery
|
174
|
+
|
175
|
+
# @private
|
176
|
+
def run_after_recovery_callbacks
|
177
|
+
self.exec_callback_yielding_self(:after_recovery)
|
178
|
+
end
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
# Called by associated connection object when AMQP connection has been re-established
|
183
|
+
# (for example, after a network failure).
|
184
|
+
#
|
185
|
+
# @api plugin
|
186
|
+
def auto_recover
|
187
|
+
self.exec_callback_yielding_self(:before_recovery)
|
188
|
+
self.resubscribe
|
189
|
+
self.exec_callback_yielding_self(:after_recovery)
|
190
|
+
end # auto_recover
|
191
|
+
|
192
|
+
# @endgroup
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
#
|
198
|
+
# Implementation
|
199
|
+
#
|
200
|
+
|
201
|
+
def handle_delivery(basic_deliver, metadata, payload)
|
202
|
+
self.exec_callback(:delivery, basic_deliver, metadata, payload)
|
203
|
+
end # handle_delivery(basic_deliver, metadata, payload)
|
204
|
+
|
205
|
+
def handle_consume_ok(consume_ok)
|
206
|
+
self.exec_callback_once(:consume, consume_ok)
|
207
|
+
end # handle_consume_ok(consume_ok)
|
208
|
+
|
209
|
+
def handle_cancel_ok(cancel_ok)
|
210
|
+
@consumer_tag = nil
|
211
|
+
|
212
|
+
# detach from object graph so that this object will be garbage-collected
|
213
|
+
@queue = nil
|
214
|
+
@channel = nil
|
215
|
+
@connection = nil
|
216
|
+
|
217
|
+
self.exec_callback_once(:cancel, cancel_ok)
|
218
|
+
end # handle_cancel_ok(method)
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
self.handle(Protocol::Basic::ConsumeOk) do |connection, frame|
|
223
|
+
channel = connection.channels[frame.channel]
|
224
|
+
consumer = channel.consumers_awaiting_consume_ok.shift
|
225
|
+
|
226
|
+
consumer.handle_consume_ok(frame.decode_payload)
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
self.handle(Protocol::Basic::CancelOk) do |connection, frame|
|
231
|
+
channel = connection.channels[frame.channel]
|
232
|
+
consumer = channel.consumers_awaiting_cancel_ok.shift
|
233
|
+
|
234
|
+
consumer.handle_consume_ok(frame.decode_payload)
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
self.handle(Protocol::Basic::Deliver) do |connection, method_frame, content_frames|
|
239
|
+
channel = connection.channels[method_frame.channel]
|
240
|
+
basic_deliver = method_frame.decode_payload
|
241
|
+
consumer = channel.consumers[basic_deliver.consumer_tag]
|
242
|
+
|
243
|
+
metadata = content_frames.shift
|
244
|
+
payload = content_frames.map { |frame| frame.payload }.join
|
245
|
+
|
246
|
+
consumer.handle_delivery(basic_deliver, metadata, payload)
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
protected
|
251
|
+
|
252
|
+
def register_with_channel
|
253
|
+
@channel.consumers[@consumer_tag] = self
|
254
|
+
end # register_with_channel
|
255
|
+
|
256
|
+
def register_with_queue
|
257
|
+
@queue.consumers[@consumer_tag] = self
|
258
|
+
end # register_with_queue
|
259
|
+
|
260
|
+
def unregister_with_channel
|
261
|
+
@channel.consumers.delete(@consumer_tag)
|
262
|
+
end # register_with_channel
|
263
|
+
|
264
|
+
def unregister_with_queue
|
265
|
+
@queue.consumers.delete(@consumer_tag)
|
266
|
+
end # register_with_queue
|
267
|
+
end # Consumer
|
268
|
+
end # Async
|
269
|
+
end # Client
|
270
|
+
end # AMQ
|