bunny 1.7.0 → 2.17.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.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/.gitignore +6 -1
- data/.rspec +1 -3
- data/.travis.yml +21 -14
- data/CONTRIBUTING.md +132 -0
- data/ChangeLog.md +745 -1
- data/Gemfile +13 -13
- data/LICENSE +1 -1
- data/README.md +41 -75
- data/Rakefile +54 -0
- data/bunny.gemspec +4 -10
- data/docker-compose.yml +28 -0
- data/docker/Dockerfile +24 -0
- data/docker/apt/preferences.d/erlang +3 -0
- data/docker/apt/sources.list.d/bintray.rabbitmq.list +2 -0
- data/docker/docker-entrypoint.sh +26 -0
- data/docker/rabbitmq.conf +29 -0
- data/examples/connection/automatic_recovery_with_basic_get.rb +1 -1
- data/examples/connection/automatic_recovery_with_client_named_queues.rb +1 -1
- data/examples/connection/automatic_recovery_with_multiple_consumers.rb +1 -1
- data/examples/connection/automatic_recovery_with_republishing.rb +1 -1
- data/examples/connection/automatic_recovery_with_server_named_queues.rb +1 -1
- data/examples/connection/channel_level_exception.rb +1 -9
- data/examples/connection/disabled_automatic_recovery.rb +1 -1
- data/examples/connection/heartbeat.rb +1 -1
- data/examples/consumers/high_and_low_priority.rb +1 -1
- data/examples/guides/extensions/alternate_exchange.rb +2 -0
- data/examples/guides/getting_started/hello_world.rb +2 -0
- data/examples/guides/getting_started/weathr.rb +2 -0
- data/examples/guides/queues/one_off_consumer.rb +2 -0
- data/examples/guides/queues/redeliveries.rb +2 -0
- data/lib/bunny.rb +6 -2
- data/lib/bunny/channel.rb +192 -109
- data/lib/bunny/channel_id_allocator.rb +6 -4
- data/lib/bunny/concurrent/continuation_queue.rb +34 -13
- data/lib/bunny/consumer_work_pool.rb +34 -6
- data/lib/bunny/cruby/socket.rb +29 -16
- data/lib/bunny/cruby/ssl_socket.rb +20 -7
- data/lib/bunny/exceptions.rb +7 -1
- data/lib/bunny/exchange.rb +11 -7
- data/lib/bunny/get_response.rb +1 -1
- data/lib/bunny/heartbeat_sender.rb +3 -2
- data/lib/bunny/jruby/socket.rb +23 -6
- data/lib/bunny/jruby/ssl_socket.rb +5 -0
- data/lib/bunny/queue.rb +12 -10
- data/lib/bunny/reader_loop.rb +31 -18
- data/lib/bunny/session.rb +389 -134
- data/lib/bunny/test_kit.rb +14 -0
- data/lib/bunny/timeout.rb +1 -12
- data/lib/bunny/transport.rb +114 -67
- data/lib/bunny/version.rb +1 -1
- data/repl +1 -1
- data/spec/config/rabbitmq.conf +13 -0
- data/spec/higher_level_api/integration/basic_ack_spec.rb +154 -22
- data/spec/higher_level_api/integration/basic_cancel_spec.rb +77 -11
- data/spec/higher_level_api/integration/basic_consume_spec.rb +60 -55
- data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +6 -6
- data/spec/higher_level_api/integration/basic_get_spec.rb +31 -7
- data/spec/higher_level_api/integration/basic_nack_spec.rb +22 -19
- data/spec/higher_level_api/integration/basic_publish_spec.rb +11 -100
- data/spec/higher_level_api/integration/basic_qos_spec.rb +32 -4
- data/spec/higher_level_api/integration/basic_reject_spec.rb +94 -16
- data/spec/higher_level_api/integration/basic_return_spec.rb +4 -4
- data/spec/higher_level_api/integration/channel_close_spec.rb +51 -10
- data/spec/higher_level_api/integration/channel_open_spec.rb +12 -12
- data/spec/higher_level_api/integration/connection_recovery_spec.rb +412 -286
- data/spec/higher_level_api/integration/connection_spec.rb +284 -134
- data/spec/higher_level_api/integration/connection_stop_spec.rb +31 -19
- data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +17 -17
- data/spec/higher_level_api/integration/dead_lettering_spec.rb +14 -14
- data/spec/higher_level_api/integration/exchange_bind_spec.rb +5 -5
- data/spec/higher_level_api/integration/exchange_declare_spec.rb +32 -31
- data/spec/higher_level_api/integration/exchange_delete_spec.rb +12 -12
- data/spec/higher_level_api/integration/exchange_unbind_spec.rb +5 -5
- data/spec/higher_level_api/integration/exclusive_queue_spec.rb +5 -5
- data/spec/higher_level_api/integration/heartbeat_spec.rb +4 -4
- data/spec/higher_level_api/integration/message_properties_access_spec.rb +49 -49
- data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +2 -2
- data/spec/higher_level_api/integration/publisher_confirms_spec.rb +92 -27
- data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +19 -19
- data/spec/higher_level_api/integration/queue_bind_spec.rb +23 -23
- data/spec/higher_level_api/integration/queue_declare_spec.rb +129 -34
- data/spec/higher_level_api/integration/queue_delete_spec.rb +2 -2
- data/spec/higher_level_api/integration/queue_purge_spec.rb +5 -5
- data/spec/higher_level_api/integration/queue_unbind_spec.rb +6 -6
- data/spec/higher_level_api/integration/read_only_consumer_spec.rb +9 -9
- data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +10 -10
- data/spec/higher_level_api/integration/tls_connection_spec.rb +218 -112
- data/spec/higher_level_api/integration/toxiproxy_spec.rb +76 -0
- data/spec/higher_level_api/integration/tx_commit_spec.rb +1 -1
- data/spec/higher_level_api/integration/tx_rollback_spec.rb +1 -1
- data/spec/higher_level_api/integration/with_channel_spec.rb +2 -2
- data/spec/issues/issue100_spec.rb +11 -12
- data/spec/issues/issue141_spec.rb +13 -14
- data/spec/issues/issue202_spec.rb +1 -1
- data/spec/issues/issue224_spec.rb +5 -5
- data/spec/issues/issue465_spec.rb +32 -0
- data/spec/issues/issue549_spec.rb +30 -0
- data/spec/issues/issue78_spec.rb +21 -24
- data/spec/issues/issue83_spec.rb +5 -6
- data/spec/issues/issue97_spec.rb +44 -45
- data/spec/lower_level_api/integration/basic_cancel_spec.rb +15 -16
- data/spec/lower_level_api/integration/basic_consume_spec.rb +20 -21
- data/spec/spec_helper.rb +2 -19
- data/spec/stress/channel_close_stress_spec.rb +3 -3
- data/spec/stress/channel_open_stress_spec.rb +4 -4
- data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +7 -7
- data/spec/stress/concurrent_consumers_stress_spec.rb +18 -16
- data/spec/stress/concurrent_publishers_stress_spec.rb +16 -19
- data/spec/stress/connection_open_close_spec.rb +9 -9
- data/spec/stress/merry_go_round_spec.rb +105 -0
- data/spec/tls/ca_certificate.pem +27 -16
- data/spec/tls/ca_key.pem +52 -27
- data/spec/tls/client_certificate.pem +27 -16
- data/spec/tls/client_key.pem +49 -25
- data/spec/tls/generate-server-cert.sh +8 -0
- data/spec/tls/server-openssl.cnf +10 -0
- data/spec/tls/server.csr +16 -0
- data/spec/tls/server_certificate.pem +27 -16
- data/spec/tls/server_key.pem +49 -25
- data/spec/toxiproxy_helper.rb +28 -0
- data/spec/unit/bunny_spec.rb +5 -5
- data/spec/unit/concurrent/atomic_fixnum_spec.rb +6 -6
- data/spec/unit/concurrent/condition_spec.rb +8 -8
- data/spec/unit/concurrent/linked_continuation_queue_spec.rb +2 -2
- data/spec/unit/concurrent/synchronized_sorted_set_spec.rb +16 -16
- data/spec/unit/exchange_recovery_spec.rb +39 -0
- data/spec/unit/version_delivery_tag_spec.rb +3 -3
- metadata +42 -35
- data/lib/bunny/system_timer.rb +0 -20
- data/spec/config/rabbitmq.config +0 -18
- data/spec/higher_level_api/integration/basic_recover_spec.rb +0 -18
- data/spec/higher_level_api/integration/confirm_select_spec.rb +0 -19
- data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +0 -50
- data/spec/higher_level_api/integration/merry_go_round_spec.rb +0 -85
- data/spec/stress/long_running_consumer_spec.rb +0 -83
- data/spec/tls/cacert.pem +0 -18
- data/spec/tls/client_cert.pem +0 -18
- data/spec/tls/server_cert.pem +0 -18
- data/spec/unit/system_timer_spec.rb +0 -10
@@ -8,17 +8,9 @@ $:.unshift(File.expand_path("../../../lib", __FILE__))
|
|
8
8
|
|
9
9
|
require 'bunny'
|
10
10
|
|
11
|
-
conn = Bunny.new(:
|
11
|
+
conn = Bunny.new(heartbeat_timeout: 8)
|
12
12
|
conn.start
|
13
13
|
|
14
|
-
begin
|
15
|
-
ch1 = conn.create_channel
|
16
|
-
ch1.queue_delete("queue_that_should_not_exist#{rand}")
|
17
|
-
rescue Bunny::NotFound => e
|
18
|
-
puts "Channel-level exception! Code: #{e.channel_close.reply_code}, message: #{e.channel_close.reply_text}"
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
14
|
begin
|
23
15
|
ch2 = conn.create_channel
|
24
16
|
q = "bunny.examples.recovery.q#{rand}"
|
@@ -8,7 +8,7 @@ $:.unshift(File.expand_path("../../../lib", __FILE__))
|
|
8
8
|
|
9
9
|
require 'bunny'
|
10
10
|
|
11
|
-
conn = Bunny.new(:
|
11
|
+
conn = Bunny.new(heartbeat_timeout: 8, automatically_recover: false)
|
12
12
|
conn.start
|
13
13
|
|
14
14
|
ch = conn.create_channel
|
@@ -11,7 +11,7 @@ require 'bunny'
|
|
11
11
|
HIGH_PRIORITY_Q = "bunny.examples.priority.hilo.high"
|
12
12
|
LOW_PRIORITY_Q = "bunny.examples.priority.hilo.low"
|
13
13
|
|
14
|
-
conn = Bunny.new(:
|
14
|
+
conn = Bunny.new(heartbeat_timeout: 8)
|
15
15
|
conn.start
|
16
16
|
|
17
17
|
ch1 = conn.create_channel
|
data/lib/bunny.rb
CHANGED
@@ -58,7 +58,7 @@ module Bunny
|
|
58
58
|
# @see http://rubybunny.info/articles/getting_started.html
|
59
59
|
# @see http://rubybunny.info/articles/connecting.html
|
60
60
|
# @api public
|
61
|
-
def self.new(connection_string_or_opts =
|
61
|
+
def self.new(connection_string_or_opts = ENV['RABBITMQ_URL'], opts = {})
|
62
62
|
if connection_string_or_opts.respond_to?(:keys) && opts.empty?
|
63
63
|
opts = connection_string_or_opts
|
64
64
|
end
|
@@ -70,9 +70,13 @@ module Bunny
|
|
70
70
|
end
|
71
71
|
|
72
72
|
|
73
|
-
def self.run(connection_string_or_opts =
|
73
|
+
def self.run(connection_string_or_opts = ENV['RABBITMQ_URL'], opts = {}, &block)
|
74
74
|
raise ArgumentError, 'Bunny#run requires a block' unless block
|
75
75
|
|
76
|
+
if connection_string_or_opts.respond_to?(:keys) && opts.empty?
|
77
|
+
opts = connection_string_or_opts
|
78
|
+
end
|
79
|
+
|
76
80
|
client = Session.new(connection_string_or_opts, opts)
|
77
81
|
|
78
82
|
begin
|
data/lib/bunny/channel.rb
CHANGED
@@ -156,6 +156,8 @@ module Bunny
|
|
156
156
|
|
157
157
|
# @return [Integer] active basic.qos prefetch value
|
158
158
|
attr_reader :prefetch_count
|
159
|
+
# @return [Integer] active basic.qos prefetch global mode
|
160
|
+
attr_reader :prefetch_global
|
159
161
|
|
160
162
|
DEFAULT_CONTENT_TYPE = "application/octet-stream".freeze
|
161
163
|
SHORTSTR_LIMIT = 255
|
@@ -167,6 +169,17 @@ module Bunny
|
|
167
169
|
@connection = connection
|
168
170
|
@logger = connection.logger
|
169
171
|
@id = id || @connection.next_channel_id
|
172
|
+
|
173
|
+
# channel allocator is exhausted
|
174
|
+
if @id < 0
|
175
|
+
msg = "Cannot open a channel: max number of channels on connection reached. Connection channel_max value: #{@connection.channel_max}"
|
176
|
+
@logger.error(msg)
|
177
|
+
|
178
|
+
raise msg
|
179
|
+
else
|
180
|
+
@logger.debug { "Allocated channel id: #{@id}" }
|
181
|
+
end
|
182
|
+
|
170
183
|
@status = :opening
|
171
184
|
|
172
185
|
@connection.register_channel(self)
|
@@ -180,6 +193,9 @@ module Bunny
|
|
180
193
|
@publishing_mutex = @connection.mutex_impl.new
|
181
194
|
@consumer_mutex = @connection.mutex_impl.new
|
182
195
|
|
196
|
+
@queue_mutex = @connection.mutex_impl.new
|
197
|
+
@exchange_mutex = @connection.mutex_impl.new
|
198
|
+
|
183
199
|
@unconfirmed_set_mutex = @connection.mutex_impl.new
|
184
200
|
|
185
201
|
self.reset_continuations
|
@@ -228,6 +244,9 @@ module Bunny
|
|
228
244
|
# {Bunny::Queue}, {Bunny::Exchange} and {Bunny::Consumer} instances.
|
229
245
|
# @api public
|
230
246
|
def close
|
247
|
+
# see bunny#528
|
248
|
+
raise_if_no_longer_open!
|
249
|
+
|
231
250
|
@connection.close_channel(self)
|
232
251
|
@status = :closed
|
233
252
|
@work_pool.shutdown
|
@@ -246,7 +265,6 @@ module Bunny
|
|
246
265
|
@status == :closed
|
247
266
|
end
|
248
267
|
|
249
|
-
|
250
268
|
#
|
251
269
|
# @group Backwards compatibility with 0.8.0
|
252
270
|
#
|
@@ -295,7 +313,7 @@ module Bunny
|
|
295
313
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
|
296
314
|
# @api public
|
297
315
|
def fanout(name, opts = {})
|
298
|
-
Exchange.new(self, :fanout, name, opts)
|
316
|
+
find_exchange(name) || Exchange.new(self, :fanout, name, opts)
|
299
317
|
end
|
300
318
|
|
301
319
|
# Declares a direct exchange or looks it up in the cache of previously
|
@@ -313,7 +331,7 @@ module Bunny
|
|
313
331
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
|
314
332
|
# @api public
|
315
333
|
def direct(name, opts = {})
|
316
|
-
Exchange.new(self, :direct, name, opts)
|
334
|
+
find_exchange(name) || Exchange.new(self, :direct, name, opts)
|
317
335
|
end
|
318
336
|
|
319
337
|
# Declares a topic exchange or looks it up in the cache of previously
|
@@ -331,7 +349,7 @@ module Bunny
|
|
331
349
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
|
332
350
|
# @api public
|
333
351
|
def topic(name, opts = {})
|
334
|
-
Exchange.new(self, :topic, name, opts)
|
352
|
+
find_exchange(name) || Exchange.new(self, :topic, name, opts)
|
335
353
|
end
|
336
354
|
|
337
355
|
# Declares a headers exchange or looks it up in the cache of previously
|
@@ -349,14 +367,14 @@ module Bunny
|
|
349
367
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
|
350
368
|
# @api public
|
351
369
|
def headers(name, opts = {})
|
352
|
-
Exchange.new(self, :headers, name, opts)
|
370
|
+
find_exchange(name) || Exchange.new(self, :headers, name, opts)
|
353
371
|
end
|
354
372
|
|
355
373
|
# Provides access to the default exchange
|
356
374
|
# @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
|
357
375
|
# @api public
|
358
376
|
def default_exchange
|
359
|
-
|
377
|
+
Exchange.default(self)
|
360
378
|
end
|
361
379
|
|
362
380
|
# Declares a headers exchange or looks it up in the cache of previously
|
@@ -397,6 +415,8 @@ module Bunny
|
|
397
415
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions guide
|
398
416
|
# @api public
|
399
417
|
def queue(name = AMQ::Protocol::EMPTY_STRING, opts = {})
|
418
|
+
throw ArgumentError.new("queue name must not be nil") if name.nil?
|
419
|
+
|
400
420
|
q = find_queue(name) || Bunny::Queue.new(self, name, opts)
|
401
421
|
|
402
422
|
register_queue(q)
|
@@ -417,17 +437,6 @@ module Bunny
|
|
417
437
|
|
418
438
|
# @group QoS and Flow Control
|
419
439
|
|
420
|
-
# Sets how many messages will be given to consumers on this channel before they
|
421
|
-
# have to acknowledge or reject one of the previously consumed messages
|
422
|
-
#
|
423
|
-
# @param [Integer] prefetch_count Prefetch (QoS setting) for this channel
|
424
|
-
# @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
|
425
|
-
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
426
|
-
# @api public
|
427
|
-
def prefetch(count)
|
428
|
-
self.basic_qos(count, false)
|
429
|
-
end
|
430
|
-
|
431
440
|
# Flow control. When set to false, RabbitMQ will stop delivering messages on this
|
432
441
|
# channel.
|
433
442
|
#
|
@@ -460,9 +469,7 @@ module Bunny
|
|
460
469
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
461
470
|
# @api public
|
462
471
|
def reject(delivery_tag, requeue = false)
|
463
|
-
|
464
|
-
basic_reject(delivery_tag.to_i, requeue)
|
465
|
-
end
|
472
|
+
basic_reject(delivery_tag.to_i, requeue)
|
466
473
|
end
|
467
474
|
|
468
475
|
# Acknowledges a message. Acknowledged messages are completely removed from the queue.
|
@@ -473,9 +480,7 @@ module Bunny
|
|
473
480
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
474
481
|
# @api public
|
475
482
|
def ack(delivery_tag, multiple = false)
|
476
|
-
|
477
|
-
basic_ack(delivery_tag.to_i, multiple)
|
478
|
-
end
|
483
|
+
basic_ack(delivery_tag.to_i, multiple)
|
479
484
|
end
|
480
485
|
alias acknowledge ack
|
481
486
|
|
@@ -490,9 +495,7 @@ module Bunny
|
|
490
495
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
491
496
|
# @api public
|
492
497
|
def nack(delivery_tag, multiple = false, requeue = false)
|
493
|
-
|
494
|
-
basic_nack(delivery_tag.to_i, multiple, requeue)
|
495
|
-
end
|
498
|
+
basic_nack(delivery_tag.to_i, multiple, requeue)
|
496
499
|
end
|
497
500
|
|
498
501
|
# @endgroup
|
@@ -562,7 +565,7 @@ module Bunny
|
|
562
565
|
opts[:mandatory],
|
563
566
|
false,
|
564
567
|
@connection.frame_max)
|
565
|
-
@connection.
|
568
|
+
@connection.send_frameset(frames, self)
|
566
569
|
|
567
570
|
self
|
568
571
|
end
|
@@ -605,40 +608,59 @@ module Bunny
|
|
605
608
|
# implementation (and even more correct and convenient ones, such as wait/notify, should
|
606
609
|
# we implement them). So we return a triple of nils immediately which apps should be
|
607
610
|
# able to handle anyway as "got no message, no need to act". MK.
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
611
|
+
last_basic_get_response = if @connection.open?
|
612
|
+
begin
|
613
|
+
wait_on_basic_get_continuations
|
614
|
+
rescue Timeout::Error => e
|
615
|
+
raise_if_continuation_resulted_in_a_channel_error!
|
616
|
+
raise e
|
617
|
+
end
|
618
|
+
else
|
619
|
+
[nil, nil, nil]
|
620
|
+
end
|
613
621
|
|
614
622
|
raise_if_continuation_resulted_in_a_channel_error!
|
615
|
-
|
623
|
+
last_basic_get_response
|
616
624
|
end
|
617
625
|
|
626
|
+
# prefetch_count is of type short in the protocol. MK.
|
627
|
+
MAX_PREFETCH_COUNT = (2 ** 16) - 1
|
628
|
+
|
618
629
|
# Controls message delivery rate using basic.qos AMQP 0.9.1 method.
|
619
630
|
#
|
620
631
|
# @param [Integer] prefetch_count How many messages can consumers on this channel be given at a time
|
621
632
|
# (before they have to acknowledge or reject one of the earlier received messages)
|
622
|
-
# @param [Boolean] global
|
633
|
+
# @param [Boolean] global
|
634
|
+
# Whether to use global mode for prefetch:
|
635
|
+
# - +false+: per-consumer
|
636
|
+
# - +true+: per-channel
|
637
|
+
# Note that the default value (+false+) hasn't actually changed, but
|
638
|
+
# previous documentation described that as meaning per-channel and
|
639
|
+
# unsupported in RabbitMQ, whereas it now actually appears to mean
|
640
|
+
# per-consumer and supported
|
641
|
+
# (https://www.rabbitmq.com/consumer-prefetch.html).
|
623
642
|
# @return [AMQ::Protocol::Basic::QosOk] RabbitMQ response
|
624
643
|
# @see Bunny::Channel#prefetch
|
625
644
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
626
645
|
# @api public
|
627
646
|
def basic_qos(count, global = false)
|
628
|
-
raise ArgumentError.new("prefetch count must be a positive integer, given: #{
|
647
|
+
raise ArgumentError.new("prefetch count must be a positive integer, given: #{count}") if count < 0
|
648
|
+
raise ArgumentError.new("prefetch count must be no greater than #{MAX_PREFETCH_COUNT}, given: #{count}") if count > MAX_PREFETCH_COUNT
|
629
649
|
raise_if_no_longer_open!
|
630
650
|
|
631
651
|
@connection.send_frame(AMQ::Protocol::Basic::Qos.encode(@id, 0, count, global))
|
632
652
|
|
633
|
-
|
653
|
+
with_continuation_timeout do
|
634
654
|
@last_basic_qos_ok = wait_on_continuations
|
635
655
|
end
|
636
656
|
raise_if_continuation_resulted_in_a_channel_error!
|
637
657
|
|
638
|
-
@prefetch_count
|
658
|
+
@prefetch_count = count
|
659
|
+
@prefetch_global = global
|
639
660
|
|
640
661
|
@last_basic_qos_ok
|
641
662
|
end
|
663
|
+
alias prefetch basic_qos
|
642
664
|
|
643
665
|
# Redeliver unacknowledged messages
|
644
666
|
#
|
@@ -649,7 +671,7 @@ module Bunny
|
|
649
671
|
raise_if_no_longer_open!
|
650
672
|
|
651
673
|
@connection.send_frame(AMQ::Protocol::Basic::Recover.encode(@id, requeue))
|
652
|
-
|
674
|
+
with_continuation_timeout do
|
653
675
|
@last_basic_recover_ok = wait_on_continuations
|
654
676
|
end
|
655
677
|
raise_if_continuation_resulted_in_a_channel_error!
|
@@ -679,7 +701,7 @@ module Bunny
|
|
679
701
|
#
|
680
702
|
# ch = conn.create_channel
|
681
703
|
# q.subscribe do |delivery_info, properties, payload|
|
682
|
-
# #
|
704
|
+
# # reject the message
|
683
705
|
# ch.basic_reject(delivery_info.delivery_tag, false)
|
684
706
|
# end
|
685
707
|
#
|
@@ -695,11 +717,13 @@ module Bunny
|
|
695
717
|
# @see Bunny::Channel#basic_nack
|
696
718
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
697
719
|
# @api public
|
698
|
-
def basic_reject(delivery_tag, requeue)
|
699
|
-
|
700
|
-
|
720
|
+
def basic_reject(delivery_tag, requeue = false)
|
721
|
+
guarding_against_stale_delivery_tags(delivery_tag) do
|
722
|
+
raise_if_no_longer_open!
|
723
|
+
@connection.send_frame(AMQ::Protocol::Basic::Reject.encode(@id, delivery_tag, requeue))
|
701
724
|
|
702
|
-
|
725
|
+
nil
|
726
|
+
end
|
703
727
|
end
|
704
728
|
|
705
729
|
# Acknowledges a delivery (message).
|
@@ -715,7 +739,7 @@ module Bunny
|
|
715
739
|
# ch = conn.create_channel
|
716
740
|
# q.subscribe do |delivery_info, properties, payload|
|
717
741
|
# # requeue the message
|
718
|
-
# ch.basic_ack(delivery_info.delivery_tag)
|
742
|
+
# ch.basic_ack(delivery_info.delivery_tag.to_i)
|
719
743
|
# end
|
720
744
|
#
|
721
745
|
# @example Ack a message fetched via basic.get
|
@@ -725,7 +749,7 @@ module Bunny
|
|
725
749
|
# ch = conn.create_channel
|
726
750
|
# # we assume the queue exists and has messages
|
727
751
|
# delivery_info, properties, payload = ch.basic_get("bunny.examples.queue3", :manual_ack => true)
|
728
|
-
# ch.basic_ack(delivery_info.delivery_tag)
|
752
|
+
# ch.basic_ack(delivery_info.delivery_tag.to_i)
|
729
753
|
#
|
730
754
|
# @example Ack multiple messages fetched via basic.get
|
731
755
|
# conn = Bunny.new
|
@@ -737,16 +761,17 @@ module Bunny
|
|
737
761
|
# _, _, payload2 = ch.basic_get("bunny.examples.queue3", :manual_ack => true)
|
738
762
|
# delivery_info, properties, payload3 = ch.basic_get("bunny.examples.queue3", :manual_ack => true)
|
739
763
|
# # ack all fetched messages up to payload3
|
740
|
-
# ch.basic_ack(delivery_info.delivery_tag, true)
|
764
|
+
# ch.basic_ack(delivery_info.delivery_tag.to_i, true)
|
741
765
|
#
|
742
766
|
# @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
|
743
|
-
# @see #basic_ack_known_delivery_tag
|
744
767
|
# @api public
|
745
|
-
def basic_ack(delivery_tag, multiple)
|
746
|
-
|
747
|
-
|
768
|
+
def basic_ack(delivery_tag, multiple = false)
|
769
|
+
guarding_against_stale_delivery_tags(delivery_tag) do
|
770
|
+
raise_if_no_longer_open!
|
771
|
+
@connection.send_frame(AMQ::Protocol::Basic::Ack.encode(@id, delivery_tag, multiple))
|
748
772
|
|
749
|
-
|
773
|
+
nil
|
774
|
+
end
|
750
775
|
end
|
751
776
|
|
752
777
|
# Rejects or requeues messages just like {Bunny::Channel#basic_reject} but can do so
|
@@ -803,13 +828,15 @@ module Bunny
|
|
803
828
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions guide
|
804
829
|
# @api public
|
805
830
|
def basic_nack(delivery_tag, multiple = false, requeue = false)
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
831
|
+
guarding_against_stale_delivery_tags(delivery_tag) do
|
832
|
+
raise_if_no_longer_open!
|
833
|
+
@connection.send_frame(AMQ::Protocol::Basic::Nack.encode(@id,
|
834
|
+
delivery_tag,
|
835
|
+
multiple,
|
836
|
+
requeue))
|
811
837
|
|
812
|
-
|
838
|
+
nil
|
839
|
+
end
|
813
840
|
end
|
814
841
|
|
815
842
|
# Registers a consumer for queue. Delivered messages will be handled with the block
|
@@ -851,7 +878,7 @@ module Bunny
|
|
851
878
|
arguments))
|
852
879
|
|
853
880
|
begin
|
854
|
-
|
881
|
+
with_continuation_timeout do
|
855
882
|
@last_basic_consume_ok = wait_on_continuations
|
856
883
|
end
|
857
884
|
rescue Exception => e
|
@@ -901,7 +928,7 @@ module Bunny
|
|
901
928
|
consumer.arguments))
|
902
929
|
|
903
930
|
begin
|
904
|
-
|
931
|
+
with_continuation_timeout do
|
905
932
|
@last_basic_consume_ok = wait_on_continuations
|
906
933
|
end
|
907
934
|
rescue Exception => e
|
@@ -936,11 +963,13 @@ module Bunny
|
|
936
963
|
def basic_cancel(consumer_tag)
|
937
964
|
@connection.send_frame(AMQ::Protocol::Basic::Cancel.encode(@id, consumer_tag, false))
|
938
965
|
|
939
|
-
|
966
|
+
with_continuation_timeout do
|
940
967
|
@last_basic_cancel_ok = wait_on_continuations
|
941
968
|
end
|
942
969
|
|
943
|
-
|
970
|
+
# reduces thread usage for channels that don't have any
|
971
|
+
# consumers
|
972
|
+
@work_pool.shutdown(true) unless self.any_consumers?
|
944
973
|
|
945
974
|
@last_basic_cancel_ok
|
946
975
|
end
|
@@ -958,7 +987,8 @@ module Bunny
|
|
958
987
|
|
959
988
|
# Declares a queue using queue.declare AMQP 0.9.1 method.
|
960
989
|
#
|
961
|
-
# @param [String] name
|
990
|
+
# @param [String] name The name of the queue or an empty string to let RabbitMQ generate a name.
|
991
|
+
# Note that LF and CR characters will be stripped from the value.
|
962
992
|
# @param [Hash] opts Queue properties
|
963
993
|
#
|
964
994
|
# @option opts [Boolean] durable (false) Should information about this queue be persisted to disk so that it
|
@@ -976,16 +1006,28 @@ module Bunny
|
|
976
1006
|
def queue_declare(name, opts = {})
|
977
1007
|
raise_if_no_longer_open!
|
978
1008
|
|
979
|
-
|
980
|
-
|
1009
|
+
# strip trailing new line and carriage returns
|
1010
|
+
# just like RabbitMQ does
|
1011
|
+
safe_name = name.gsub(/[\r\n]/, "")
|
1012
|
+
@pending_queue_declare_name = safe_name
|
1013
|
+
@connection.send_frame(
|
1014
|
+
AMQ::Protocol::Queue::Declare.encode(@id,
|
1015
|
+
@pending_queue_declare_name,
|
981
1016
|
opts.fetch(:passive, false),
|
982
1017
|
opts.fetch(:durable, false),
|
983
1018
|
opts.fetch(:exclusive, false),
|
984
1019
|
opts.fetch(:auto_delete, false),
|
985
1020
|
false,
|
986
1021
|
opts[:arguments]))
|
987
|
-
@last_queue_declare_ok = wait_on_continuations
|
988
1022
|
|
1023
|
+
begin
|
1024
|
+
with_continuation_timeout do
|
1025
|
+
@last_queue_declare_ok = wait_on_continuations
|
1026
|
+
end
|
1027
|
+
ensure
|
1028
|
+
# clear pending continuation context if it belongs to us
|
1029
|
+
@pending_queue_declare_name = nil if @pending_queue_declare_name == safe_name
|
1030
|
+
end
|
989
1031
|
raise_if_continuation_resulted_in_a_channel_error!
|
990
1032
|
|
991
1033
|
@last_queue_declare_ok
|
@@ -1010,7 +1052,7 @@ module Bunny
|
|
1010
1052
|
opts[:if_unused],
|
1011
1053
|
opts[:if_empty],
|
1012
1054
|
false))
|
1013
|
-
|
1055
|
+
with_continuation_timeout do
|
1014
1056
|
@last_queue_delete_ok = wait_on_continuations
|
1015
1057
|
end
|
1016
1058
|
raise_if_continuation_resulted_in_a_channel_error!
|
@@ -1030,7 +1072,7 @@ module Bunny
|
|
1030
1072
|
|
1031
1073
|
@connection.send_frame(AMQ::Protocol::Queue::Purge.encode(@id, name, false))
|
1032
1074
|
|
1033
|
-
|
1075
|
+
with_continuation_timeout do
|
1034
1076
|
@last_queue_purge_ok = wait_on_continuations
|
1035
1077
|
end
|
1036
1078
|
raise_if_continuation_resulted_in_a_channel_error!
|
@@ -1066,7 +1108,7 @@ module Bunny
|
|
1066
1108
|
(opts[:routing_key] || opts[:key]),
|
1067
1109
|
false,
|
1068
1110
|
opts[:arguments]))
|
1069
|
-
|
1111
|
+
with_continuation_timeout do
|
1070
1112
|
@last_queue_bind_ok = wait_on_continuations
|
1071
1113
|
end
|
1072
1114
|
|
@@ -1101,7 +1143,7 @@ module Bunny
|
|
1101
1143
|
exchange_name,
|
1102
1144
|
opts[:routing_key],
|
1103
1145
|
opts[:arguments]))
|
1104
|
-
|
1146
|
+
with_continuation_timeout do
|
1105
1147
|
@last_queue_unbind_ok = wait_on_continuations
|
1106
1148
|
end
|
1107
1149
|
|
@@ -1114,26 +1156,30 @@ module Bunny
|
|
1114
1156
|
|
1115
1157
|
# @group Exchange operations (exchange.*)
|
1116
1158
|
|
1117
|
-
# Declares a
|
1159
|
+
# Declares a exchange using exchange.declare AMQP 0.9.1 method.
|
1118
1160
|
#
|
1119
|
-
# @param [String] name
|
1161
|
+
# @param [String] name The name of the exchange. Note that LF and CR characters
|
1162
|
+
# will be stripped from the value.
|
1120
1163
|
# @param [String,Symbol] type Exchange type, e.g. :fanout or :topic
|
1121
1164
|
# @param [Hash] opts Exchange properties
|
1122
1165
|
#
|
1123
|
-
# @option opts [Boolean] durable (false) Should information about this
|
1166
|
+
# @option opts [Boolean] durable (false) Should information about this exchange be persisted to disk so that it
|
1124
1167
|
# can survive broker restarts? Typically set to true for long-lived exchanges.
|
1125
|
-
# @option opts [Boolean] auto_delete (false) Should this
|
1168
|
+
# @option opts [Boolean] auto_delete (false) Should this exchange be deleted when it is no longer used?
|
1126
1169
|
# @option opts [Boolean] passive (false) If true, exchange will be checked for existence. If it does not
|
1127
1170
|
# exist, {Bunny::NotFound} will be raised.
|
1128
1171
|
#
|
1129
1172
|
# @return [AMQ::Protocol::Exchange::DeclareOk] RabbitMQ response
|
1130
|
-
# @see http://rubybunny.info/articles/
|
1173
|
+
# @see http://rubybunny.info/articles/exchanges.html Exchanges and Publishing guide
|
1131
1174
|
# @api public
|
1132
1175
|
def exchange_declare(name, type, opts = {})
|
1133
1176
|
raise_if_no_longer_open!
|
1134
1177
|
|
1178
|
+
# strip trailing new line and carriage returns
|
1179
|
+
# just like RabbitMQ does
|
1180
|
+
safe_name = name.gsub(/[\r\n]/, "")
|
1135
1181
|
@connection.send_frame(AMQ::Protocol::Exchange::Declare.encode(@id,
|
1136
|
-
|
1182
|
+
safe_name,
|
1137
1183
|
type.to_s,
|
1138
1184
|
opts.fetch(:passive, false),
|
1139
1185
|
opts.fetch(:durable, false),
|
@@ -1141,7 +1187,7 @@ module Bunny
|
|
1141
1187
|
opts.fetch(:internal, false),
|
1142
1188
|
false, # nowait
|
1143
1189
|
opts[:arguments]))
|
1144
|
-
|
1190
|
+
with_continuation_timeout do
|
1145
1191
|
@last_exchange_declare_ok = wait_on_continuations
|
1146
1192
|
end
|
1147
1193
|
|
@@ -1166,7 +1212,7 @@ module Bunny
|
|
1166
1212
|
name,
|
1167
1213
|
opts[:if_unused],
|
1168
1214
|
false))
|
1169
|
-
|
1215
|
+
with_continuation_timeout do
|
1170
1216
|
@last_exchange_delete_ok = wait_on_continuations
|
1171
1217
|
end
|
1172
1218
|
|
@@ -1210,7 +1256,7 @@ module Bunny
|
|
1210
1256
|
opts[:routing_key],
|
1211
1257
|
false,
|
1212
1258
|
opts[:arguments]))
|
1213
|
-
|
1259
|
+
with_continuation_timeout do
|
1214
1260
|
@last_exchange_bind_ok = wait_on_continuations
|
1215
1261
|
end
|
1216
1262
|
|
@@ -1254,7 +1300,7 @@ module Bunny
|
|
1254
1300
|
opts[:routing_key],
|
1255
1301
|
false,
|
1256
1302
|
opts[:arguments]))
|
1257
|
-
|
1303
|
+
with_continuation_timeout do
|
1258
1304
|
@last_exchange_unbind_ok = wait_on_continuations
|
1259
1305
|
end
|
1260
1306
|
|
@@ -1282,7 +1328,7 @@ module Bunny
|
|
1282
1328
|
raise_if_no_longer_open!
|
1283
1329
|
|
1284
1330
|
@connection.send_frame(AMQ::Protocol::Channel::Flow.encode(@id, active))
|
1285
|
-
|
1331
|
+
with_continuation_timeout do
|
1286
1332
|
@last_channel_flow_ok = wait_on_continuations
|
1287
1333
|
end
|
1288
1334
|
raise_if_continuation_resulted_in_a_channel_error!
|
@@ -1303,7 +1349,7 @@ module Bunny
|
|
1303
1349
|
raise_if_no_longer_open!
|
1304
1350
|
|
1305
1351
|
@connection.send_frame(AMQ::Protocol::Tx::Select.encode(@id))
|
1306
|
-
|
1352
|
+
with_continuation_timeout do
|
1307
1353
|
@last_tx_select_ok = wait_on_continuations
|
1308
1354
|
end
|
1309
1355
|
raise_if_continuation_resulted_in_a_channel_error!
|
@@ -1319,7 +1365,7 @@ module Bunny
|
|
1319
1365
|
raise_if_no_longer_open!
|
1320
1366
|
|
1321
1367
|
@connection.send_frame(AMQ::Protocol::Tx::Commit.encode(@id))
|
1322
|
-
|
1368
|
+
with_continuation_timeout do
|
1323
1369
|
@last_tx_commit_ok = wait_on_continuations
|
1324
1370
|
end
|
1325
1371
|
raise_if_continuation_resulted_in_a_channel_error!
|
@@ -1334,7 +1380,7 @@ module Bunny
|
|
1334
1380
|
raise_if_no_longer_open!
|
1335
1381
|
|
1336
1382
|
@connection.send_frame(AMQ::Protocol::Tx::Rollback.encode(@id))
|
1337
|
-
|
1383
|
+
with_continuation_timeout do
|
1338
1384
|
@last_tx_rollback_ok = wait_on_continuations
|
1339
1385
|
end
|
1340
1386
|
raise_if_continuation_resulted_in_a_channel_error!
|
@@ -1367,7 +1413,7 @@ module Bunny
|
|
1367
1413
|
# @see #nacked_set
|
1368
1414
|
# @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions guide
|
1369
1415
|
# @api public
|
1370
|
-
def confirm_select(callback=nil)
|
1416
|
+
def confirm_select(callback = nil)
|
1371
1417
|
raise_if_no_longer_open!
|
1372
1418
|
|
1373
1419
|
if @next_publish_seq_no == 0
|
@@ -1381,10 +1427,9 @@ module Bunny
|
|
1381
1427
|
@confirms_callback = callback
|
1382
1428
|
|
1383
1429
|
@connection.send_frame(AMQ::Protocol::Confirm::Select.encode(@id, false))
|
1384
|
-
|
1430
|
+
with_continuation_timeout do
|
1385
1431
|
@last_confirm_select_ok = wait_on_continuations
|
1386
1432
|
end
|
1387
|
-
@confirm_mode = true
|
1388
1433
|
raise_if_continuation_resulted_in_a_channel_error!
|
1389
1434
|
@last_confirm_select_ok
|
1390
1435
|
end
|
@@ -1457,7 +1502,7 @@ module Bunny
|
|
1457
1502
|
#
|
1458
1503
|
# @api plugin
|
1459
1504
|
def recover_from_network_failure
|
1460
|
-
@logger.debug "Recovering channel #{@id} after network failure"
|
1505
|
+
@logger.debug { "Recovering channel #{@id} after network failure" }
|
1461
1506
|
release_all_continuations
|
1462
1507
|
|
1463
1508
|
recover_prefetch_setting
|
@@ -1475,7 +1520,7 @@ module Bunny
|
|
1475
1520
|
#
|
1476
1521
|
# @api plugin
|
1477
1522
|
def recover_prefetch_setting
|
1478
|
-
basic_qos(@prefetch_count) if @prefetch_count
|
1523
|
+
basic_qos(@prefetch_count, @prefetch_global) if @prefetch_count
|
1479
1524
|
end
|
1480
1525
|
|
1481
1526
|
# Recovers publisher confirms mode. Used by the Automatic Network Failure
|
@@ -1484,6 +1529,7 @@ module Bunny
|
|
1484
1529
|
# @api plugin
|
1485
1530
|
def recover_confirm_mode
|
1486
1531
|
if using_publisher_confirmations?
|
1532
|
+
@unconfirmed_set.clear
|
1487
1533
|
@delivery_tag_offset = @next_publish_seq_no - 1
|
1488
1534
|
confirm_select(@confirms_callback)
|
1489
1535
|
end
|
@@ -1502,7 +1548,7 @@ module Bunny
|
|
1502
1548
|
#
|
1503
1549
|
# @api plugin
|
1504
1550
|
def recover_exchanges
|
1505
|
-
@exchanges.values.
|
1551
|
+
@exchange_mutex.synchronize { @exchanges.values }.each do |x|
|
1506
1552
|
x.recover_from_network_failure
|
1507
1553
|
end
|
1508
1554
|
end
|
@@ -1512,8 +1558,8 @@ module Bunny
|
|
1512
1558
|
#
|
1513
1559
|
# @api plugin
|
1514
1560
|
def recover_queues
|
1515
|
-
@queues.values.
|
1516
|
-
@logger.debug "Recovering queue #{q.name}"
|
1561
|
+
@queue_mutex.synchronize { @queues.values }.each do |q|
|
1562
|
+
@logger.debug { "Recovering queue #{q.name}" }
|
1517
1563
|
q.recover_from_network_failure
|
1518
1564
|
end
|
1519
1565
|
end
|
@@ -1524,10 +1570,11 @@ module Bunny
|
|
1524
1570
|
# @api plugin
|
1525
1571
|
def recover_consumers
|
1526
1572
|
unless @consumers.empty?
|
1527
|
-
@work_pool = ConsumerWorkPool.new(@work_pool.size)
|
1573
|
+
@work_pool = ConsumerWorkPool.new(@work_pool.size, @work_pool.abort_on_exception)
|
1528
1574
|
@work_pool.start
|
1529
1575
|
end
|
1530
|
-
|
1576
|
+
|
1577
|
+
@consumer_mutex.synchronize { @consumers.values }.each do |c|
|
1531
1578
|
c.recover_from_network_failure
|
1532
1579
|
end
|
1533
1580
|
end
|
@@ -1552,7 +1599,11 @@ module Bunny
|
|
1552
1599
|
|
1553
1600
|
# @return [String] Brief human-readable representation of the channel
|
1554
1601
|
def to_s
|
1555
|
-
"#<#{self.class.name}:#{object_id} @id=#{self.number} @connection=#{@connection.to_s}>"
|
1602
|
+
"#<#{self.class.name}:#{object_id} @id=#{self.number} @connection=#{@connection.to_s}> @open=#{open?}"
|
1603
|
+
end
|
1604
|
+
|
1605
|
+
def inspect
|
1606
|
+
to_s
|
1556
1607
|
end
|
1557
1608
|
|
1558
1609
|
|
@@ -1560,6 +1611,11 @@ module Bunny
|
|
1560
1611
|
# Implementation
|
1561
1612
|
#
|
1562
1613
|
|
1614
|
+
# @private
|
1615
|
+
def with_continuation_timeout(&block)
|
1616
|
+
Bunny::Timeout.timeout(wait_on_continuations_timeout, ClientTimeout, &block)
|
1617
|
+
end
|
1618
|
+
|
1563
1619
|
# @private
|
1564
1620
|
def register_consumer(consumer_tag, consumer)
|
1565
1621
|
@consumer_mutex.synchronize do
|
@@ -1583,12 +1639,33 @@ module Bunny
|
|
1583
1639
|
end
|
1584
1640
|
end
|
1585
1641
|
|
1642
|
+
# @private
|
1643
|
+
def pending_server_named_queue_declaration?
|
1644
|
+
@pending_queue_declare_name && @pending_queue_declare_name.empty?
|
1645
|
+
end
|
1646
|
+
|
1647
|
+
# @private
|
1648
|
+
def can_accept_queue_declare_ok?(method)
|
1649
|
+
@pending_queue_declare_name == method.queue ||
|
1650
|
+
pending_server_named_queue_declaration?
|
1651
|
+
end
|
1652
|
+
|
1586
1653
|
# @private
|
1587
1654
|
def handle_method(method)
|
1588
|
-
@logger.debug "Channel#handle_frame on channel #{@id}: #{method.inspect}"
|
1655
|
+
@logger.debug { "Channel#handle_frame on channel #{@id}: #{method.inspect}" }
|
1589
1656
|
case method
|
1590
1657
|
when AMQ::Protocol::Queue::DeclareOk then
|
1591
|
-
|
1658
|
+
# safeguard against late arrivals of responses and
|
1659
|
+
# so on, see ruby-amqp/bunny#558
|
1660
|
+
if can_accept_queue_declare_ok?(method)
|
1661
|
+
@continuations.push(method)
|
1662
|
+
else
|
1663
|
+
if !pending_server_named_queue_declaration?
|
1664
|
+
# this response is for an outdated/overwritten
|
1665
|
+
# queue.declare, drop it
|
1666
|
+
@logger.warn "Received a queue.declare-ok response for a mismatching queue (#{method.queue} instead of #{@pending_queue_declare_name}) on channel #{@id} possibly due to a timeout, ignoring it"
|
1667
|
+
end
|
1668
|
+
end
|
1592
1669
|
when AMQ::Protocol::Queue::DeleteOk then
|
1593
1670
|
@continuations.push(method)
|
1594
1671
|
when AMQ::Protocol::Queue::PurgeOk then
|
@@ -1771,16 +1848,16 @@ module Bunny
|
|
1771
1848
|
|
1772
1849
|
# @private
|
1773
1850
|
def wait_on_confirms_continuations
|
1851
|
+
raise_if_no_longer_open!
|
1852
|
+
|
1774
1853
|
if @connection.threaded
|
1775
1854
|
t = Thread.current
|
1776
1855
|
@threads_waiting_on_confirms_continuations << t
|
1777
1856
|
|
1778
1857
|
begin
|
1779
|
-
|
1780
|
-
|
1781
|
-
outstanding_confirms = !@unconfirmed_set.empty?
|
1858
|
+
while @unconfirmed_set_mutex.synchronize { !@unconfirmed_set.empty? }
|
1859
|
+
@confirms_continuations.poll(@connection.continuation_timeout)
|
1782
1860
|
end
|
1783
|
-
@confirms_continuations.poll(@connection.continuation_timeout) if outstanding_confirms
|
1784
1861
|
ensure
|
1785
1862
|
@threads_waiting_on_confirms_continuations.delete(t)
|
1786
1863
|
end
|
@@ -1847,37 +1924,37 @@ module Bunny
|
|
1847
1924
|
|
1848
1925
|
# @private
|
1849
1926
|
def deregister_queue(queue)
|
1850
|
-
@queues.delete(queue.name)
|
1927
|
+
@queue_mutex.synchronize { @queues.delete(queue.name) }
|
1851
1928
|
end
|
1852
1929
|
|
1853
1930
|
# @private
|
1854
1931
|
def deregister_queue_named(name)
|
1855
|
-
@queues.delete(name)
|
1932
|
+
@queue_mutex.synchronize { @queues.delete(name) }
|
1856
1933
|
end
|
1857
1934
|
|
1858
1935
|
# @private
|
1859
1936
|
def register_queue(queue)
|
1860
|
-
@queues[queue.name] = queue
|
1937
|
+
@queue_mutex.synchronize { @queues[queue.name] = queue }
|
1861
1938
|
end
|
1862
1939
|
|
1863
1940
|
# @private
|
1864
1941
|
def find_queue(name)
|
1865
|
-
@queues[name]
|
1942
|
+
@queue_mutex.synchronize { @queues[name] }
|
1866
1943
|
end
|
1867
1944
|
|
1868
1945
|
# @private
|
1869
1946
|
def deregister_exchange(exchange)
|
1870
|
-
@exchanges.delete(exchange.name)
|
1947
|
+
@exchange_mutex.synchronize { @exchanges.delete(exchange.name) }
|
1871
1948
|
end
|
1872
1949
|
|
1873
1950
|
# @private
|
1874
1951
|
def register_exchange(exchange)
|
1875
|
-
@exchanges[exchange.name] = exchange
|
1952
|
+
@exchange_mutex.synchronize { @exchanges[exchange.name] = exchange }
|
1876
1953
|
end
|
1877
1954
|
|
1878
1955
|
# @private
|
1879
1956
|
def find_exchange(name)
|
1880
|
-
@exchanges[name]
|
1957
|
+
@exchange_mutex.synchronize { @exchanges[name] }
|
1881
1958
|
end
|
1882
1959
|
|
1883
1960
|
protected
|
@@ -1917,7 +1994,13 @@ module Bunny
|
|
1917
1994
|
|
1918
1995
|
# @private
|
1919
1996
|
def raise_if_no_longer_open!
|
1920
|
-
|
1997
|
+
if closed?
|
1998
|
+
if @last_channel_error
|
1999
|
+
raise ChannelAlreadyClosed.new("cannot use a closed channel! Channel id: #{@id}, closed due to a server-reported channel error: #{@last_channel_error.message}", self)
|
2000
|
+
else
|
2001
|
+
raise ChannelAlreadyClosed.new("cannot use a closed channel! Channel id: #{@id}", self)
|
2002
|
+
end
|
2003
|
+
end
|
1921
2004
|
end
|
1922
2005
|
|
1923
2006
|
# @private
|
@@ -1957,7 +2040,7 @@ module Bunny
|
|
1957
2040
|
def guarding_against_stale_delivery_tags(tag, &block)
|
1958
2041
|
case tag
|
1959
2042
|
# if a fixnum was passed, execute unconditionally. MK.
|
1960
|
-
when
|
2043
|
+
when Integer then
|
1961
2044
|
block.call
|
1962
2045
|
# versioned delivery tags should be checked to avoid
|
1963
2046
|
# sending out stale (invalid) tags after channel was reopened
|