amqp 0.8.0.rc12 → 0.8.0.rc13
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/.yardopts +2 -1
- data/CONTRIBUTORS +29 -22
- data/Gemfile +2 -1
- data/README.md +241 -0
- data/amqp.gemspec +7 -5
- data/bin/set_test_suite_realms_up.sh +6 -6
- data/docs/08Migration.textile +3 -1
- data/docs/Bindings.textile +3 -1
- data/docs/Clustering.textile +4 -0
- data/docs/ConnectingToTheBroker.textile +108 -86
- data/docs/ConnectionEncryptionWithTLS.textile +3 -1
- data/docs/DocumentationGuidesIndex.textile +24 -2
- data/docs/Durability.textile +22 -1
- data/docs/ErrorHandling.textile +21 -1
- data/docs/Exchanges.textile +181 -9
- data/docs/GettingStarted.textile +65 -167
- data/docs/Queues.textile +400 -355
- data/docs/RabbitMQVersions.textile +34 -3
- data/docs/Routing.textile +4 -1
- data/docs/RunningTests.textile +116 -0
- data/docs/Troubleshooting.textile +131 -0
- data/docs/VendorSpecificExtensions.textile +20 -0
- data/examples/channels/qos_aka_prefetch.rb +3 -3
- data/examples/channels/qos_aka_prefetch_without_callback.rb +2 -2
- data/examples/error_handling/channel_level_exception.rb +1 -1
- data/examples/error_handling/channel_level_exception_with_multiple_channels_involved.rb +1 -0
- data/examples/error_handling/connection_level_exception.rb +26 -0
- data/examples/error_handling/global_channel_level_exception_handler.rb +3 -3
- data/examples/exchanges/autodeletion_of_exchanges.rb +37 -0
- data/examples/extensions/rabbitmq/per_queue_message_ttl.rb +3 -3
- data/examples/extensions/rabbitmq/publisher_confirmations_with_transient_messages.rb +2 -2
- data/examples/guides/getting_started/{03_babblr.rb → 03_blabbr.rb} +0 -0
- data/examples/guides/queues/01a_declaring_a_server_named_queue_using_queue_constructor.rb +18 -0
- data/examples/guides/queues/01b_declaring_a_queue_using_queue_constructor.rb +18 -0
- data/examples/guides/queues/02a_declaring_a_durable_shared_queue.rb +18 -0
- data/examples/guides/queues/02b_declaring_a_durable_shared_queue.rb +18 -0
- data/examples/guides/queues/03a_declaring_a_temporary_exclusive_queue.rb +19 -0
- data/examples/guides/queues/03b_declaring_a_temporary_exclusive_queue.rb +18 -0
- data/examples/guides/queues/{05_binding_a_queue_using_exchange_instance.rb → 04_bind_a_queue_using_exchange_instance.rb} +2 -2
- data/examples/guides/queues/{06_biding_a_queue_using_exchange_name_string.rb → 05_bind_a_queue_using_exchange_name.rb} +2 -2
- data/examples/guides/queues/{07_subscribing_to_receive_messages.rb → 06_subscribe_to_receive_messages.rb} +1 -1
- data/examples/guides/queues/{08_poll_for_messages.rb → 07_fetch_a_message_from_the_queue.rb} +1 -1
- data/examples/guides/queues/{09_unsubscribing_a_consumer.rb → 08_unsubscribing_a_consumer.rb} +0 -0
- data/examples/guides/queues/{10_unbinding_from_exchange.rb → 09_unbinding_from_exchange.rb} +2 -2
- data/examples/guides/queues/{11_purge_a_queue.rb → 10_purge_a_queue.rb} +2 -2
- data/examples/guides/queues/{12_deleting_a_queue.rb → 11_deleting_a_queue.rb} +2 -2
- data/examples/hello_world.rb +1 -1
- data/examples/hello_world_with_an_empty_string.rb +33 -0
- data/examples/issues/amq_client_issue_7.rb +31 -0
- data/examples/issues/amq_protocol_issue_14.rb +46 -0
- data/examples/issues/issue_75.rb +23 -0
- data/examples/issues/issue_79.rb +35 -0
- data/examples/issues/issue_80.rb +40 -0
- data/examples/publishing/{publishing_and_immediately_stopping_event_loop.rb → publishing_a_one_off_message.rb} +9 -12
- data/examples/publishing/publishing_callback.rb +52 -0
- data/examples/publishing/returned_messages.rb +3 -3
- data/examples/queues/accessing_message_metadata.rb +60 -0
- data/examples/queues/queue_status.rb +0 -7
- data/examples/queues/rejecting_messages_without_requeueuing.rb +47 -0
- data/examples/queues/using_explicit_acknowledgements.rb +96 -0
- data/examples/routing/headers_routing.rb +54 -0
- data/lib/amqp/channel.rb +245 -40
- data/lib/amqp/client.rb +23 -11
- data/lib/amqp/exchange.rb +58 -41
- data/lib/amqp/queue.rb +66 -13
- data/lib/amqp/version.rb +1 -1
- data/spec/integration/authentication_spec.rb +5 -5
- data/spec/integration/basic_get_spec.rb +1 -1
- data/spec/integration/channel_close_spec.rb +10 -3
- data/spec/integration/queue_declaration_spec.rb +26 -5
- data/spec/integration/topic_subscription_spec.rb +1 -1
- data/spec/unit/amqp/client_spec.rb +7 -54
- data/tasks.rb +1 -8
- metadata +64 -23
- data/README.textile +0 -229
data/lib/amqp/client.rb
CHANGED
@@ -40,32 +40,42 @@ module AMQP
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
# Parses AMQP connection
|
43
|
+
# Parses AMQP connection URI and returns its components as a hash.
|
44
44
|
#
|
45
45
|
# h2. vhost naming schemes
|
46
46
|
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
47
|
+
# It is convenient to be able to specify the AMQP connection
|
48
|
+
# parameters as a URI string, and various "amqp" URI schemes
|
49
|
+
# exist. Unfortunately, there is no standard for these URIs, so
|
50
|
+
# while the schemes share the basic idea, they differ in some
|
51
|
+
# details. This implementation aims to encourage URIs that work
|
52
|
+
# as widely as possible.
|
50
53
|
#
|
51
|
-
#
|
54
|
+
# The URI scheme should be "amqp", or "amqps" if SSL is required.
|
55
|
+
#
|
56
|
+
# The host, port, username and password are represented in the
|
57
|
+
# authority component of the URI in the same way as in http URIs.
|
58
|
+
#
|
59
|
+
# The vhost is obtained from the first segment of the path, with the
|
60
|
+
# leading slash removed. The path should contain only a single
|
61
|
+
# segment (i.e, the only slash in it should be the leading one).
|
62
|
+
# If the vhost is to include slashes or other reserved URI
|
63
|
+
# characters, these should be percent-escaped.
|
52
64
|
#
|
53
65
|
# @example How vhost is parsed
|
54
66
|
#
|
55
67
|
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com") # => vhost is nil, so default (/) will be used
|
56
68
|
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/") # => vhost is an empty string
|
57
|
-
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com//") # => vhost is /
|
58
|
-
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com//vault") # => vhost is /vault
|
59
69
|
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/%2Fvault") # => vhost is /vault
|
60
70
|
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/production") # => vhost is production
|
61
71
|
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/a.b.c") # => vhost is a.b.c
|
62
|
-
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com
|
72
|
+
# AMQP::Client.parse_connection_uri("amqp://dev.rabbitmq.com/foo/bar") # => ArgumentError
|
63
73
|
#
|
64
74
|
#
|
65
75
|
# @param [String] connection_string AMQP connection URI, à la JDBC connection string. For example: amqp://bus.megacorp.internal:5877.
|
66
76
|
# @return [Hash] Connection parameters (:username, :password, :vhost, :host, :port, :ssl)
|
67
77
|
#
|
68
|
-
# @raise [ArgumentError] When connection URI schema is not amqp or amqps
|
78
|
+
# @raise [ArgumentError] When connection URI schema is not amqp or amqps, or the path contains multiple segments
|
69
79
|
#
|
70
80
|
# @see http://bit.ly/ks8MXK Connecting to The Broker documentation guide
|
71
81
|
# @api public
|
@@ -75,14 +85,16 @@ module AMQP
|
|
75
85
|
|
76
86
|
opts = {}
|
77
87
|
|
78
|
-
|
79
88
|
opts[:scheme] = uri.scheme
|
80
89
|
opts[:user] = URI.unescape(uri.user) if uri.user
|
81
90
|
opts[:pass] = URI.unescape(uri.password) if uri.password
|
82
|
-
opts[:vhost] = URI.unescape($1) if uri.path =~ %r{^/(.*)}
|
83
91
|
opts[:host] = uri.host if uri.host
|
84
92
|
opts[:port] = uri.port || AMQP_PORTS[uri.scheme]
|
85
93
|
opts[:ssl] = uri.scheme == AMQPS
|
94
|
+
if uri.path =~ %r{^/(.*)}
|
95
|
+
raise ArgumentError.new("#{uri} has multiple-segment path; please percent-encode any slashes in the vhost name (e.g. /production => %2Fproduction). Learn more at http://bit.ly/amqp-gem-and-connection-uris") if $1.index('/')
|
96
|
+
opts[:vhost] = URI.unescape($1)
|
97
|
+
end
|
86
98
|
|
87
99
|
opts
|
88
100
|
end
|
data/lib/amqp/exchange.rb
CHANGED
@@ -366,8 +366,10 @@ module AMQP
|
|
366
366
|
|
367
367
|
# Publishes message to the exchange. The message will be routed to queues by the exchange
|
368
368
|
# and distributed to any active consumers. Routing logic is determined by exchange type and
|
369
|
-
# configuration as well as
|
369
|
+
# configuration as well as message attributes (like :routing_key or message headers).
|
370
370
|
#
|
371
|
+
# Published data is opaque and not modified by Ruby amqp gem in any way. Serialization of data with JSON, Thrift, BSON
|
372
|
+
# or similar libraries before publishing is very common.
|
371
373
|
#
|
372
374
|
#
|
373
375
|
# h2. Data serialization
|
@@ -375,14 +377,48 @@ module AMQP
|
|
375
377
|
# Note that this method calls #to_s on payload argument value. You are encouraged to take care of
|
376
378
|
# data serialization before publishing (using JSON, Thrift, Protocol Buffers or other serialization library).
|
377
379
|
# Note that because AMQP is a binary protocol, text formats like JSON lose lose their strong point of being easy
|
378
|
-
# to inspect data as it travels across network.
|
380
|
+
# to inspect data as it travels across network. For the same reason BSON may be a good fit.
|
379
381
|
#
|
380
382
|
#
|
383
|
+
# h2. Publishing and message persistence
|
384
|
+
#
|
385
|
+
# In cases when you application cannot afford to lose a message, AMQP 0.9.1 has several features to offer:
|
386
|
+
#
|
387
|
+
# * Persistent messages
|
388
|
+
# * Messages acknowledgements
|
389
|
+
# * Transactions
|
390
|
+
# * (a RabbitMQ-specific extension) Publisher confirms
|
391
|
+
#
|
392
|
+
# This is a broad topic and we dedicate a separate guide, {file:docs/Durability.textile Durability and message persistence}, to it.
|
393
|
+
#
|
394
|
+
#
|
395
|
+
# h2. Publishing callback and guarantees it DOES NOT offer
|
396
|
+
#
|
397
|
+
# Exact moment when message is published is not determined and depends on many factors, including machine's networking stack configuration,
|
398
|
+
# so (optional) block this method takes is scheduled for next event loop tick, and data is staged for delivery for current event loop
|
399
|
+
# tick. For most applications, this is good enough. The only way to guarantee a message was delivered in a distributed system is to
|
400
|
+
# ask a peer to send you a message back. RabbitMQ
|
401
|
+
#
|
402
|
+
# @note Optional callback this method takes DOES NOT OFFER ANY GUARANTEES ABOUT DATA DELIVERY and must not be used as a "delivery callback".
|
403
|
+
# The only way to guarantee delivery in distributed environment is to use an acknowledgement mechanism, such as AMQP transactions
|
404
|
+
# or lightweight "publisher confirms" RabbitMQ extension supported by amqp gem. See {file:docs/Durability.textile Durability and message persistence}
|
405
|
+
# and {file:docs/Exchanges.textile Working With Exchanges} guides for details.
|
406
|
+
#
|
381
407
|
#
|
382
408
|
# h2. Event loop blocking
|
383
409
|
#
|
384
|
-
#
|
385
|
-
#
|
410
|
+
# When intermixing publishing of many messages with other workload that may take some time, even loop blocking may affect the performance.
|
411
|
+
# There are several ways to avoid it:
|
412
|
+
#
|
413
|
+
# * Run EventMachine in a separate thread.
|
414
|
+
# * Use EventMachine.next_tick.
|
415
|
+
# * Use EventMachine.defer to offload operation to EventMachine thread pool.
|
416
|
+
#
|
417
|
+
# TBD: this subject is worth a separate guide
|
418
|
+
#
|
419
|
+
#
|
420
|
+
# h2. Sending one-off messages
|
421
|
+
#
|
386
422
|
# If you need to send a one-off message and then stop the event loop, pass a block to {Exchange#publish} that will be executed
|
387
423
|
# after message is pushed down the network stack, and use {AMQP::Session#disconnect} to properly tear down AMQP connection
|
388
424
|
# (see example under Examples section below).
|
@@ -393,18 +429,6 @@ module AMQP
|
|
393
429
|
# end
|
394
430
|
#
|
395
431
|
#
|
396
|
-
# h2. Publishing and persistence
|
397
|
-
#
|
398
|
-
# In cases when you application cannot afford to lose a message, AMQP 0.9.1 has several features to offer:
|
399
|
-
#
|
400
|
-
# * Persistent messages
|
401
|
-
# * Messages acknowledgements
|
402
|
-
# * Transactions
|
403
|
-
# * (a RabbitMQ-specific extension) Publisher confirms
|
404
|
-
#
|
405
|
-
# This is a broad topic and we dedicate a separate guide, {file:docs/Durability.textile Durability and message persistence}, to it.
|
406
|
-
#
|
407
|
-
#
|
408
432
|
#
|
409
433
|
# @param [#to_s] payload Message payload (content). Note that this method calls #to_s on payload argument value.
|
410
434
|
# You are encouraged to take care of data serialization before publishing (using JSON, Thrift,
|
@@ -446,48 +470,41 @@ module AMQP
|
|
446
470
|
#
|
447
471
|
# @return [Exchange] self
|
448
472
|
#
|
449
|
-
# @note Please make sure you read {file:docs/Durability.textile Durability
|
473
|
+
# @note Please make sure you read {file:docs/Durability.textile Durability an message persistence} guide that covers exchanges durability vs. messages
|
450
474
|
# persistence.
|
451
475
|
# @api public
|
452
476
|
def publish(payload, options = {}, &block)
|
453
|
-
|
454
|
-
opts = @default_publish_options.merge(options)
|
477
|
+
opts = @default_publish_options.merge(options)
|
455
478
|
|
456
|
-
|
457
|
-
|
479
|
+
@channel.once_open do
|
480
|
+
super(payload.to_s, opts[:key] || opts[:routing_key] || @default_routing_key, @default_headers.merge(options), opts[:mandatory], opts[:immediate])
|
458
481
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
end
|
482
|
+
# don't pass block to AMQ::Client::Exchange#publish because it will be executed
|
483
|
+
# immediately and we want to do it later. See ruby-amqp/amqp/#67 MK.
|
484
|
+
EventMachine.next_tick(&block) if block
|
463
485
|
end
|
464
486
|
|
465
487
|
self
|
466
488
|
end
|
467
489
|
|
468
490
|
|
469
|
-
# This method deletes an exchange.
|
470
|
-
#
|
491
|
+
# This method deletes an exchange. When an exchange is deleted all queue bindings on the exchange are deleted, too.
|
492
|
+
# Further attempts to publish messages to a deleted exchange will result in a channel-level exception.
|
471
493
|
#
|
472
|
-
#
|
473
|
-
# an AMQP::Channel::Error due to a channel close exception.
|
494
|
+
# @example Deleting an exchange
|
474
495
|
#
|
475
|
-
# exchange = AMQP::Channel.direct(
|
496
|
+
# exchange = AMQP::Channel.direct("search.indexing")
|
476
497
|
# exchange.delete
|
477
498
|
#
|
478
|
-
#
|
479
|
-
#
|
480
|
-
#
|
481
|
-
# not wait for a reply method. If the server could not complete the
|
482
|
-
# method it will raise a channel or connection exception.
|
483
|
-
#
|
484
|
-
# exchange.delete(:nowait => false)
|
499
|
+
# @option opts [Boolean] :nowait (false) If set, the server will not respond to the method. The client should
|
500
|
+
# not wait for a reply method. If the server could not complete the
|
501
|
+
# method it will raise a channel or connection exception.
|
485
502
|
#
|
486
|
-
#
|
487
|
-
# If
|
488
|
-
#
|
489
|
-
# delete it but raises a channel exception instead (AMQP::Error).
|
503
|
+
# @option opts [Boolean] :if_unused (false) If set, the server will only delete the exchange if it has no queue
|
504
|
+
# bindings. If the exchange has queue bindings the server does not
|
505
|
+
# delete it but raises a channel exception instead.
|
490
506
|
#
|
507
|
+
# @return [NilClass] nil
|
491
508
|
# @api public
|
492
509
|
def delete(opts = {}, &block)
|
493
510
|
@channel.once_open do
|
data/lib/amqp/queue.rb
CHANGED
@@ -170,11 +170,16 @@ module AMQP
|
|
170
170
|
#
|
171
171
|
# @api public
|
172
172
|
def initialize(channel, name = AMQ::Protocol::EMPTY_STRING, opts = {}, &block)
|
173
|
+
raise ArgumentError.new("queue name must not be nil; if you want broker to generate queue name for you, pass an empty string") if name.nil?
|
174
|
+
|
173
175
|
@channel = channel
|
174
176
|
name = AMQ::Protocol::EMPTY_STRING if name.nil?
|
175
177
|
@name = name unless name.empty?
|
176
178
|
@server_named = name.empty?
|
177
179
|
@opts = self.class.add_default_options(name, opts, block)
|
180
|
+
|
181
|
+
raise ArgumentError.new("server-named queues (name = '') declaration with :nowait => true makes no sense. If you are not sure what that means, simply drop :nowait => true from opts.") if @server_named && @opts[:nowait]
|
182
|
+
|
178
183
|
@bindings = Hash.new
|
179
184
|
|
180
185
|
# a deferrable that we use to delay operations until this queue is actually declared.
|
@@ -254,6 +259,10 @@ module AMQP
|
|
254
259
|
# name is empty, the routing key will be the current queue for the
|
255
260
|
# channel, which is the last declared queue.
|
256
261
|
#
|
262
|
+
# @option opts [Hash] :arguments (nil) A hash of optional arguments with the declaration. Headers exchange type uses these metadata
|
263
|
+
# attributes for routing matching.
|
264
|
+
# In addition, brokers may implement AMQP extensions using x-prefixed declaration arguments.
|
265
|
+
#
|
257
266
|
# @option opts [Boolean] :nowait (true) If set, the server will not respond to the method. The client should
|
258
267
|
# not wait for a reply method. If the server could not complete the
|
259
268
|
# method it will raise a channel or connection exception.
|
@@ -472,7 +481,7 @@ module AMQP
|
|
472
481
|
#
|
473
482
|
# @example Use of callback with a single argument
|
474
483
|
#
|
475
|
-
#
|
484
|
+
# EventMachine.run do
|
476
485
|
# exchange = AMQP::Channel.direct("foo queue")
|
477
486
|
# EM.add_periodic_timer(1) do
|
478
487
|
# exchange.publish("random number #{rand(1000)}")
|
@@ -488,19 +497,55 @@ module AMQP
|
|
488
497
|
#
|
489
498
|
# @example Use of callback with two arguments
|
490
499
|
#
|
491
|
-
#
|
492
|
-
#
|
493
|
-
#
|
494
|
-
#
|
500
|
+
# EventMachine.run do
|
501
|
+
# connection = AMQP.connect(:host => '127.0.0.1')
|
502
|
+
# puts "Connected to AMQP broker. Running #{AMQP::VERSION} version of the gem..."
|
503
|
+
#
|
504
|
+
# channel = AMQP::Channel.new(connection)
|
505
|
+
# queue = channel.queue("amqpgem.examples.hello_world", :auto_delete => true)
|
506
|
+
# exchange = channel.direct("amq.direct")
|
507
|
+
#
|
508
|
+
# queue.bind(exchange)
|
509
|
+
#
|
510
|
+
# channel.on_error do |ch, channel_close|
|
511
|
+
# puts channel_close.reply_text
|
512
|
+
# connection.close { EventMachine.stop }
|
495
513
|
# end
|
496
514
|
#
|
497
|
-
#
|
498
|
-
#
|
499
|
-
#
|
500
|
-
#
|
501
|
-
#
|
502
|
-
# puts "
|
515
|
+
# queue.subscribe do |metadata, payload|
|
516
|
+
# puts "metadata.routing_key : #{metadata.routing_key}"
|
517
|
+
# puts "metadata.content_type: #{metadata.content_type}"
|
518
|
+
# puts "metadata.priority : #{metadata.priority}"
|
519
|
+
# puts "metadata.headers : #{metadata.headers.inspect}"
|
520
|
+
# puts "metadata.timestamp : #{metadata.timestamp.inspect}"
|
521
|
+
# puts "metadata.type : #{metadata.type}"
|
522
|
+
# puts "metadata.delivery_tag: #{metadata.delivery_tag}"
|
523
|
+
# puts "metadata.redelivered : #{metadata.redelivered}"
|
524
|
+
#
|
525
|
+
# puts "metadata.app_id : #{metadata.app_id}"
|
526
|
+
# puts "metadata.exchange : #{metadata.exchange}"
|
527
|
+
# puts
|
528
|
+
# puts "Received a message: #{payload}. Disconnecting..."
|
529
|
+
#
|
530
|
+
# connection.close {
|
531
|
+
# EventMachine.stop { exit }
|
532
|
+
# }
|
503
533
|
# end
|
534
|
+
#
|
535
|
+
# exchange.publish("Hello, world!",
|
536
|
+
# :app_id => "amqpgem.example",
|
537
|
+
# :priority => 8,
|
538
|
+
# :type => "kinda.checkin",
|
539
|
+
# # headers table keys can be anything
|
540
|
+
# :headers => {
|
541
|
+
# :coordinates => {
|
542
|
+
# :latitude => 59.35,
|
543
|
+
# :longitude => 18.066667
|
544
|
+
# },
|
545
|
+
# :participants => 11,
|
546
|
+
# :venue => "Stockholm"
|
547
|
+
# },
|
548
|
+
# :timestamp => Time.now.to_i)
|
504
549
|
# end
|
505
550
|
#
|
506
551
|
#
|
@@ -516,10 +561,15 @@ module AMQP
|
|
516
561
|
# method it will raise a channel or connection exception.
|
517
562
|
#
|
518
563
|
# @option opts [#call] :confirm (nil) If set, this proc will be called when the server confirms subscription
|
519
|
-
# to the queue with a
|
564
|
+
# to the queue with a basic.consume-ok message. Setting this option will
|
520
565
|
# automatically set :nowait => false. This is required for the server
|
521
566
|
# to send a confirmation.
|
522
567
|
#
|
568
|
+
# @option opts [Boolean] :exclusive (false) Request exclusive consumer access, meaning only this consumer can access the queue.
|
569
|
+
# This is useful when you want a long-lived shared queue to be temporarily accessible by just
|
570
|
+
# one application (or thread, or process). If application exclusive consumer is part of crashes
|
571
|
+
# or loses network connection to the broker, channel is closed and exclusive consumer is thus cancelled.
|
572
|
+
#
|
523
573
|
#
|
524
574
|
# @yield [headers, payload] When block only takes one argument, yields payload to it. In case of two arguments, yields headers and payload.
|
525
575
|
# @yieldparam [AMQP::Header] headers Headers (metadata) associated with this message (for example, routing key).
|
@@ -527,6 +577,9 @@ module AMQP
|
|
527
577
|
#
|
528
578
|
# @return [Queue] Self
|
529
579
|
# @api public
|
580
|
+
#
|
581
|
+
# @see file:docs/Queues.textile Documentation guide on queues
|
582
|
+
# @see #unsubscribe
|
530
583
|
def subscribe(opts = {}, &block)
|
531
584
|
raise Error, 'already subscribed to the queue' if @consumer_tag
|
532
585
|
|
@@ -662,7 +715,7 @@ module AMQP
|
|
662
715
|
|
663
716
|
# @private
|
664
717
|
def self.add_default_options(name, opts, block)
|
665
|
-
{ :queue => name, :nowait => block.nil? }.merge(opts)
|
718
|
+
{ :queue => name, :nowait => (block.nil? && !name.empty?) }.merge(opts)
|
666
719
|
end
|
667
720
|
|
668
721
|
private
|
data/lib/amqp/version.rb
CHANGED
@@ -46,11 +46,11 @@ describe "Authentication attempt" do
|
|
46
46
|
#
|
47
47
|
|
48
48
|
# assuming there is an account amqp_gem with password of "amqp_gem_password" that has
|
49
|
-
# access to
|
49
|
+
# access to amqp_gem_testbed
|
50
50
|
context "when amqp_gem/amqp_gem_testbed has access to amqp_gem_testbed" do
|
51
51
|
context "and provided credentials are correct" do
|
52
52
|
it "succeeds" do
|
53
|
-
connection = AMQP.connect(AMQP_OPTS.merge(:username => "amqp_gem", :password => "amqp_gem_password", :vhost => "
|
53
|
+
connection = AMQP.connect(AMQP_OPTS.merge(:username => "amqp_gem", :password => "amqp_gem_password", :vhost => "amqp_gem_testbed"))
|
54
54
|
|
55
55
|
done(0.4) {
|
56
56
|
connection.should be_connected
|
@@ -70,7 +70,7 @@ describe "Authentication attempt" do
|
|
70
70
|
callback_has_fired = true
|
71
71
|
done
|
72
72
|
}
|
73
|
-
connection = AMQP.connect(:username => "amqp_gem", :password => Time.now.to_i.to_s, :vhost => "
|
73
|
+
connection = AMQP.connect(:username => "amqp_gem", :password => Time.now.to_i.to_s, :vhost => "amqp_gem_testbed", :on_possible_authentication_failure => handler)
|
74
74
|
end # it
|
75
75
|
end
|
76
76
|
|
@@ -100,11 +100,11 @@ describe "Authentication attempt" do
|
|
100
100
|
#
|
101
101
|
|
102
102
|
# assuming there is an account amqp_gem with password of "amqp_gem_password" that has
|
103
|
-
# access to
|
103
|
+
# access to amqp_gem_testbed
|
104
104
|
context "when amqp_gem/amqp_gem_testbed has access to amqp_gem_testbed" do
|
105
105
|
context "and provided credentials are correct" do
|
106
106
|
it "succeeds" do
|
107
|
-
connection = AMQP.connect "amqp://amqp_gem:amqp_gem_password@localhost
|
107
|
+
connection = AMQP.connect "amqp://amqp_gem:amqp_gem_password@localhost/amqp_gem_testbed"
|
108
108
|
|
109
109
|
done(0.3) {
|
110
110
|
connection.should be_connected
|
@@ -6,10 +6,17 @@ describe AMQP::Channel, "#close(&callback)" do
|
|
6
6
|
include EventedSpec::AMQPSpec
|
7
7
|
|
8
8
|
it "takes a callback which will run when we get back Channel.Close-Ok" do
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
@events = []
|
10
|
+
|
11
|
+
AMQP::Channel.new do |ch|
|
12
|
+
@events << :open_ok
|
13
|
+
ch.close do |channel, close_ok|
|
14
|
+
@events << :close_ok
|
12
15
|
end
|
13
16
|
end
|
17
|
+
|
18
|
+
done(0.3) {
|
19
|
+
@events.should == [:open_ok, :close_ok]
|
20
|
+
}
|
14
21
|
end
|
15
22
|
end
|
@@ -43,12 +43,33 @@ describe AMQP do
|
|
43
43
|
end # context
|
44
44
|
|
45
45
|
context "when queue name is passed on as an empty string" do
|
46
|
-
|
47
|
-
|
48
|
-
queue
|
49
|
-
|
50
|
-
|
46
|
+
context "and :nowait isn't used" do
|
47
|
+
it "uses server-assigned queue name" do
|
48
|
+
@channel.queue("") do |queue, *args|
|
49
|
+
queue.name.should_not be_empty
|
50
|
+
queue.delete
|
51
|
+
done(0.3)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
context "and :nowait is used" do
|
58
|
+
it "raises ArgumentError" do
|
59
|
+
expect { AMQP::Queue.new(@channel, "", :nowait => true) }.to raise_error(ArgumentError, /makes no sense/)
|
60
|
+
expect { @channel.queue("", :nowait => true) }.to raise_error(ArgumentError, /makes no sense/)
|
61
|
+
|
62
|
+
done
|
51
63
|
end
|
64
|
+
end # context
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when queue name is nil" do
|
68
|
+
it "raises ArgumentError" do
|
69
|
+
expect { AMQP::Queue.new(@channel, nil) }.to raise_error(ArgumentError, /queue name must not be nil/)
|
70
|
+
expect { @channel.queue(nil) }.to raise_error(ArgumentError, /queue name must not be nil/)
|
71
|
+
|
72
|
+
done
|
52
73
|
end
|
53
74
|
end # context
|
54
75
|
|