amqp 0.8.0.rc2 → 0.8.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -3
- data/.travis.yml +5 -2
- data/.yardopts +2 -0
- data/CHANGELOG +17 -20
- data/Gemfile +7 -5
- data/README.textile +67 -29
- data/Rakefile +6 -0
- data/amqp.gemspec +5 -5
- data/docs/08Migration.textile +27 -0
- data/docs/Bindings.textile +27 -0
- data/docs/ConnectingToTheBroker.textile +277 -0
- data/docs/DocumentationGuidesIndex.textile +25 -0
- data/docs/Durability.textile +27 -0
- data/docs/ErrorHandling.textile +84 -0
- data/docs/Exchanges.textile +27 -0
- data/docs/GettingStarted.textile +585 -0
- data/docs/Queues.textile +27 -0
- data/docs/RabbitMQVersions.textile +12 -2
- data/docs/Routing.textile +27 -0
- data/docs/TLS.textile +27 -0
- data/docs/VendorSpecificExtensions.textile +11 -1
- data/examples/{various → channels}/open_channel_without_assignment.rb +0 -4
- data/examples/channels/prefetch_as_constructor_argument.rb +31 -0
- data/examples/channels/qos_aka_prefetch.rb +34 -0
- data/examples/channels/qos_aka_prefetch_without_callback.rb +32 -0
- data/examples/error_handling/channel_level_exception.rb +47 -0
- data/examples/error_handling/channel_level_exception_with_multiple_channels_involved.rb +54 -0
- data/examples/error_handling/connection_loss_handler.rb +39 -0
- data/examples/error_handling/global_channel_level_exception_handler.rb +65 -0
- data/examples/error_handling/handling_authentication_failure_with_a_callback.rb +33 -0
- data/examples/error_handling/tcp_connection_failure_handling_with_a_rescue_block.rb +30 -0
- data/examples/error_handling/tcp_connection_failure_with_a_callback.rb +28 -0
- data/examples/{various → exchanges}/declare_an_exchange_without_assignment.rb +0 -4
- data/examples/guides/getting_started/01_hello_world.rb +24 -0
- data/examples/guides/getting_started/02_hello_world_dslified.rb +23 -0
- data/examples/guides/getting_started/03_babblr.rb +33 -0
- data/examples/guides/getting_started/04_weathr.rb +56 -0
- data/examples/hello_world.rb +12 -13
- data/examples/hello_world_with_eventmachine_in_a_separate_thread.rb +37 -0
- data/examples/{various → legacy}/ack.rb +0 -0
- data/examples/{various → legacy}/callbacks.rb +0 -0
- data/examples/{various → legacy}/clock.rb +0 -0
- data/examples/{various → legacy}/hashtable.rb +0 -0
- data/examples/{various → legacy}/logger.rb +0 -0
- data/examples/{various → legacy}/multiclock.rb +0 -0
- data/examples/{various → legacy}/pingpong.rb +0 -2
- data/examples/{various → legacy}/primes-simple.rb +0 -0
- data/examples/{various → legacy}/primes.rb +0 -2
- data/examples/{various → legacy}/stocks.rb +0 -0
- data/examples/{various → queues}/automatic_binding_for_default_direct_exchange.rb +4 -0
- data/examples/{various → queues}/basic_get.rb +0 -2
- data/examples/{various → queues}/declare_a_queue_without_assignment.rb +0 -4
- data/examples/queues/declare_and_bind_a_server_named_queue.rb +43 -0
- data/examples/{various → queues}/queue_status.rb +3 -8
- data/examples/{various → routing}/pubsub.rb +0 -0
- data/examples/{various → routing}/weather_updates.rb +1 -1
- data/lib/amqp/channel.rb +231 -52
- data/lib/amqp/client.rb +6 -3
- data/lib/amqp/connection.rb +9 -10
- data/lib/amqp/deprecated/fork.rb +3 -3
- data/lib/amqp/deprecated/logger.rb +1 -0
- data/lib/amqp/deprecated/mq.rb +23 -1
- data/lib/amqp/deprecated/rpc.rb +1 -0
- data/lib/amqp/exceptions.rb +45 -3
- data/lib/amqp/exchange.rb +29 -35
- data/lib/amqp/ext/em.rb +0 -7
- data/lib/amqp/ext/emfork.rb +3 -2
- data/lib/amqp/header.rb +4 -0
- data/lib/amqp/queue.rb +96 -33
- data/lib/amqp/session.rb +140 -0
- data/lib/amqp/version.rb +6 -1
- data/spec/integration/automatic_binding_for_default_direct_exchange_spec.rb +7 -7
- data/spec/integration/channel_level_exception_with_multiple_channels_spec.rb +69 -0
- data/spec/integration/declare_and_immediately_bind_a_server_named_queue_spec.rb +42 -0
- data/spec/integration/queue_declaration_spec.rb +8 -24
- data/spec/integration/queue_redeclaration_with_incompatible_attributes_spec.rb +43 -0
- data/spec/unit/amqp/connection_spec.rb +1 -1
- metadata +200 -182
- data/lib/amqp/basic_client.rb +0 -27
data/lib/amqp/connection.rb
CHANGED
@@ -75,15 +75,16 @@ module AMQP
|
|
75
75
|
@connection.closing?
|
76
76
|
end
|
77
77
|
|
78
|
-
|
78
|
+
# @return [Boolean] Current global logging value
|
79
79
|
# @api public
|
80
80
|
def self.logging
|
81
81
|
self.settings[:logging]
|
82
82
|
end
|
83
83
|
|
84
|
+
# @return [Boolean] Sets current global logging value
|
84
85
|
# @api public
|
85
86
|
def self.logging=(value)
|
86
|
-
self.settings[:logging] = !!
|
87
|
+
self.settings[:logging] = !!value
|
87
88
|
end
|
88
89
|
|
89
90
|
# Default connection. When you do not pass connection instance to methods like
|
@@ -94,6 +95,7 @@ module AMQP
|
|
94
95
|
@connection
|
95
96
|
end
|
96
97
|
|
98
|
+
# Sets global connection object.
|
97
99
|
# @api public
|
98
100
|
def self.connection=(value)
|
99
101
|
@connection = value
|
@@ -144,7 +146,7 @@ module AMQP
|
|
144
146
|
# # ...
|
145
147
|
# end
|
146
148
|
# end
|
147
|
-
#
|
149
|
+
#
|
148
150
|
#
|
149
151
|
# @overload connect(connection_string, options = {})
|
150
152
|
# Used to pass connection parameters as a connection string
|
@@ -161,7 +163,7 @@ module AMQP
|
|
161
163
|
# @option connection_options_or_string [String] :username ("guest") Username to use. Also can be specified as :user.
|
162
164
|
# @option connection_options_or_string [String] :password ("guest") Password to use. Also can be specified as :pass.
|
163
165
|
# @option connection_options_or_string [Hash] :ssl TLS (SSL) parameters to use.
|
164
|
-
# @option connection_options_or_string [#call] :on_possible_authentication_failure A callable object that will be run if authentication fails (see Authentication failure section)
|
166
|
+
# @option connection_options_or_string [#call] :on_possible_authentication_failure A callable object that will be run if authentication fails (see Authentication failure section)
|
165
167
|
#
|
166
168
|
#
|
167
169
|
# h2. Handling authentication failures
|
@@ -175,18 +177,15 @@ module AMQP
|
|
175
177
|
# with :on_possible_authentication_failure option.
|
176
178
|
#
|
177
179
|
# @note This method assumes that EventMachine even loop is already running. If it is not the case or you are not sure, we recommend you use {AMQP.start} instead. It takes exactly the same parameters.
|
180
|
+
# @return [AMQP::Session]
|
178
181
|
# @api public
|
179
182
|
def self.connect(connection_options_or_string = {}, other_options = {}, &block)
|
180
183
|
Client.connect(connection_options_or_string, other_options, &block)
|
181
184
|
end
|
182
185
|
|
183
|
-
# @return [Hash]
|
186
|
+
# @return [Hash] Default AMQP connection settings. This hash may be modified.
|
184
187
|
# @api public
|
185
188
|
def self.settings
|
186
|
-
|
187
|
-
@connection.settings
|
188
|
-
else
|
189
|
-
AMQ::Client::Settings.default
|
190
|
-
end
|
189
|
+
@settings ||= AMQ::Client::Settings.default
|
191
190
|
end
|
192
191
|
end # AMQP
|
data/lib/amqp/deprecated/fork.rb
CHANGED
data/lib/amqp/deprecated/mq.rb
CHANGED
@@ -17,4 +17,26 @@ class MQ
|
|
17
17
|
# @note This class will be removed before 1.0 release.
|
18
18
|
# @deprecated
|
19
19
|
class Queue < ::AMQP::Queue; end
|
20
|
-
|
20
|
+
|
21
|
+
|
22
|
+
#
|
23
|
+
# Backwards compatibility with 0.6.x
|
24
|
+
#
|
25
|
+
|
26
|
+
# unique identifier
|
27
|
+
def MQ.id
|
28
|
+
Thread.current[:mq_id] ||= "#{`hostname`.strip}-#{Process.pid}-#{Thread.current.object_id}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# @private
|
32
|
+
def MQ.default
|
33
|
+
# TODO: clear this when connection is closed
|
34
|
+
Thread.current[:mq] ||= MQ.new
|
35
|
+
end
|
36
|
+
|
37
|
+
# Allows for calls to all MQ instance methods. This implicitly calls
|
38
|
+
# MQ.new so that a new channel is allocated for subsequent operations.
|
39
|
+
def MQ.method_missing(meth, *args, &blk)
|
40
|
+
MQ.default.__send__(meth, *args, &blk)
|
41
|
+
end
|
42
|
+
end
|
data/lib/amqp/deprecated/rpc.rb
CHANGED
data/lib/amqp/exceptions.rb
CHANGED
@@ -1,18 +1,60 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module AMQP
|
4
|
-
#
|
5
|
-
|
4
|
+
# Base class for AMQP connection lifecycle exceptions.
|
5
|
+
# @api public
|
6
|
+
class Error < StandardError
|
7
|
+
# An exception in one of the underlying libraries that caused this
|
8
|
+
# exception to be re-thrown. May be nil.
|
9
|
+
attr_reader :cause
|
10
|
+
end
|
6
11
|
|
12
|
+
|
13
|
+
# All the exceptions below are new in 0.8.0. Previous versions
|
14
|
+
# used AMQP::Error for everything. We have to carry this baggage but
|
15
|
+
# there is a way out: simply subclass AMQP::Error and provide a backwards-compatible
|
16
|
+
# way of attaching root cause exception (like AMQ::Client::TCPConnectionFailed) instance
|
17
|
+
# to it.
|
18
|
+
#
|
19
|
+
# In other words: AMQP::Error is here to stay for a long time. MK.
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
# Raised when initial TCP connection to the broker fails.
|
24
|
+
# @api public
|
25
|
+
class TCPConnectionFailed < Error
|
26
|
+
|
27
|
+
#
|
28
|
+
# API
|
29
|
+
#
|
30
|
+
|
31
|
+
# @return [Hash] connection settings that were used
|
32
|
+
attr_reader :settings
|
33
|
+
|
34
|
+
def initialize(settings, cause = nil)
|
35
|
+
@settings = settings
|
36
|
+
@cause = cause
|
37
|
+
|
38
|
+
super("Could not estabilish TCP connection to #{@settings[:host]}:#{@settings[:port]}")
|
39
|
+
end # TCPConnectionFailed
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# Raised when queue (or exchange) declaration fails because another queue with the same
|
44
|
+
# name but different attributes already exists in the channel object cache.
|
45
|
+
# @api public
|
7
46
|
class IncompatibleOptionsError < Error
|
8
47
|
def initialize(name, opts_1, opts_2)
|
9
48
|
super("There is already an instance called #{name} with options #{opts_1.inspect}, you can't define the same instance with different options (#{opts_2.inspect})!")
|
10
49
|
end
|
11
50
|
end # IncompatibleOptionsError
|
12
51
|
|
52
|
+
# Raised on attempt to use a channel that was previously closed
|
53
|
+
# (either due to channel-level exception or intentionally via AMQP::Channel#close).
|
54
|
+
# @api public
|
13
55
|
class ChannelClosedError < Error
|
14
56
|
def initialize(instance)
|
15
|
-
super("
|
57
|
+
super("Channel with id = #{instance.channel} is closed, you can't use it anymore!")
|
16
58
|
end
|
17
59
|
end # ChannelClosedError
|
18
60
|
end # AMQP
|
data/lib/amqp/exchange.rb
CHANGED
@@ -12,18 +12,10 @@ module AMQP
|
|
12
12
|
# type and message attributes, determines how to deliver the message.
|
13
13
|
#
|
14
14
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# As part of the standard, the server _must_ predeclare the direct exchange
|
20
|
-
# 'amq.direct' and the fanout exchange 'amq.fanout'. All exchange names
|
21
|
-
# starting with 'amq.' are reserved: attempts to declare an exchange using
|
22
|
-
# 'amq.' as the name will raise an AMQP::Error and fail.
|
23
|
-
#
|
24
|
-
# Note that durability of exchanges and durability of messages published to exchanges
|
25
|
-
# are different concepts. Sending messages to durable exchanges does not make
|
26
|
-
# messages themselves persistent.
|
15
|
+
# Entities that forward messages to consumers (or consumers fetch messages
|
16
|
+
# from on demand) are called {Queue queues}. Exchanges are associated with
|
17
|
+
# queues via bindings. Roughly speaking, bindings determine messages placed
|
18
|
+
# in what exchange end up in what queues.
|
27
19
|
#
|
28
20
|
#
|
29
21
|
# h2. AMQP bindings
|
@@ -36,16 +28,10 @@ module AMQP
|
|
36
28
|
# queue.
|
37
29
|
#
|
38
30
|
#
|
39
|
-
#
|
40
|
-
# point for all published messages.
|
41
|
-
#
|
42
|
-
# There are three (3) supported Exchange types: direct, fanout and topic.
|
31
|
+
# h2. Exchange types
|
43
32
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
# starting with 'amq.' are reserved). Attempts to declare an exchange using
|
47
|
-
# 'amq.' as the name will raise an AMQP::Error and fail. In practice these
|
48
|
-
# default exchanges are never used directly by client code.
|
33
|
+
# There are 4 supported exchange types: direct, fanout, topic and headers.
|
34
|
+
# Exchange type determines how exchange processes and routes messages.
|
49
35
|
#
|
50
36
|
#
|
51
37
|
# h2. Direct exchanges
|
@@ -61,6 +47,11 @@ module AMQP
|
|
61
47
|
# queue names. In other words, messages delivered to default exchange are routed to queues when
|
62
48
|
# message routing key equals queue name. Default exchange name is an empty string.
|
63
49
|
#
|
50
|
+
# As part of the standard, the server _must_ predeclare the direct exchange
|
51
|
+
# 'amq.direct' and the fanout exchange 'amq.fanout' (all exchange names
|
52
|
+
# starting with 'amq.' are reserved). Attempts to declare an exchange using
|
53
|
+
# 'amq.' as the name will raise an AMQP::Error and fail. In practice these
|
54
|
+
# default exchanges are never used directly by client code.
|
64
55
|
#
|
65
56
|
#
|
66
57
|
# h2. Fanout exchanges
|
@@ -71,7 +62,6 @@ module AMQP
|
|
71
62
|
# Each queue gets it's own copy of the message.
|
72
63
|
#
|
73
64
|
#
|
74
|
-
#
|
75
65
|
# h2. Topic exchanges
|
76
66
|
#
|
77
67
|
# Topic exchanges are used for 1:n and n:m communication scenarios.
|
@@ -96,10 +86,7 @@ module AMQP
|
|
96
86
|
#
|
97
87
|
# h2. Headers exchanges
|
98
88
|
#
|
99
|
-
#
|
100
|
-
# exchange named 'amq.match'.
|
101
|
-
#
|
102
|
-
# When publishing data to the exchange, bound queues subscribing to the
|
89
|
+
# When publishing data to exchange of type headers, bound queues subscribing to the
|
103
90
|
# exchange indicate which data interests them by passing arguments
|
104
91
|
# for matching against the headers in published messages. The
|
105
92
|
# form of the matching can be controlled by the 'x-match' argument, which
|
@@ -109,6 +96,19 @@ module AMQP
|
|
109
96
|
# it does an AND of the headers ), while a value of 'any' implies that
|
110
97
|
# at least one should match (ie. it does an OR).
|
111
98
|
#
|
99
|
+
# As part of the AMQP standard, each server _should_ predeclare a headers
|
100
|
+
# exchange named 'amq.match'.
|
101
|
+
#
|
102
|
+
#
|
103
|
+
# h2. Key methods
|
104
|
+
#
|
105
|
+
# Key methods of Exchange class are
|
106
|
+
#
|
107
|
+
# * {Exchange#publish}
|
108
|
+
# * {Exchange#delete}
|
109
|
+
# * {Exchange.default}
|
110
|
+
#
|
111
|
+
#
|
112
112
|
#
|
113
113
|
# h2. Exchange durability and persistence of messages.
|
114
114
|
#
|
@@ -124,7 +124,8 @@ module AMQP
|
|
124
124
|
# Publishing messages as persistent affects performance (just like with data stores, durability comes at a certain cost
|
125
125
|
# in performance and vise versa). Pass :persistent => true to {Exchange#publish} to publish your message as persistent.
|
126
126
|
#
|
127
|
-
# Note that *only durable queues can be bound to durable exchanges*.
|
127
|
+
# Note that *only durable queues can be bound to durable exchanges*. Learn more in our {file:docs/Durability.textile Durability guide}.
|
128
|
+
#
|
128
129
|
#
|
129
130
|
#
|
130
131
|
# h2. RabbitMQ extensions.
|
@@ -133,14 +134,6 @@ module AMQP
|
|
133
134
|
# Learn more in {file:docs/VendorSpecificExtensions.textile}
|
134
135
|
#
|
135
136
|
#
|
136
|
-
# h2. Key methods
|
137
|
-
#
|
138
|
-
# Key methods of Exchange class are
|
139
|
-
#
|
140
|
-
# * {Exchange#publish}
|
141
|
-
# * {Exchange#delete}
|
142
|
-
# * {Exchange.default}
|
143
|
-
#
|
144
137
|
#
|
145
138
|
# @note Please make sure you read a section on exchanges durability vs. messages
|
146
139
|
# persistence.
|
@@ -517,6 +510,7 @@ module AMQP
|
|
517
510
|
|
518
511
|
protected
|
519
512
|
|
513
|
+
# @private
|
520
514
|
def self.add_default_options(type, name, opts, block)
|
521
515
|
{ :exchange => name, :type => type, :nowait => block.nil? }.merge(opts)
|
522
516
|
end
|
data/lib/amqp/ext/em.rb
CHANGED
data/lib/amqp/ext/emfork.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# @private
|
3
4
|
EMFORK = $0 == __FILE__
|
4
5
|
|
5
6
|
if EMFORK
|
@@ -8,9 +9,8 @@ end
|
|
8
9
|
|
9
10
|
require 'eventmachine'
|
10
11
|
|
11
|
-
#:stopdoc:
|
12
|
-
|
13
12
|
# helper to fork off EM reactors
|
13
|
+
# @private
|
14
14
|
def EM.fork num = 1, &blk
|
15
15
|
unless @forks
|
16
16
|
trap('CHLD') {
|
@@ -47,6 +47,7 @@ def EM.fork num = 1, &blk
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
# @private
|
50
51
|
def EM.forks
|
51
52
|
@forks ? @forks.keys : []
|
52
53
|
end
|
data/lib/amqp/header.rb
CHANGED
@@ -38,6 +38,8 @@ module AMQP
|
|
38
38
|
@channel.reject(@method.delivery_tag, opts.fetch(:requeue, false))
|
39
39
|
end
|
40
40
|
|
41
|
+
# @return [Hash] AMQP message header w/o method-specific information.
|
42
|
+
# @api public
|
41
43
|
def to_hash
|
42
44
|
@header
|
43
45
|
end # to_hash
|
@@ -46,6 +48,8 @@ module AMQP
|
|
46
48
|
(@header && args.empty? && blk.nil? && @header.has_key?(meth)) || @method.respond_to?(meth)
|
47
49
|
end
|
48
50
|
|
51
|
+
# Returns AMQP message attributes.
|
52
|
+
# @api public
|
49
53
|
def method_missing(meth, *args, &blk)
|
50
54
|
if @header && args.empty? && blk.nil? && @header.has_key?(meth)
|
51
55
|
@header[meth]
|
data/lib/amqp/queue.rb
CHANGED
@@ -10,27 +10,83 @@ module AMQP
|
|
10
10
|
# to queues and finally queues deliver them to consumer applications (or consumer
|
11
11
|
# applications fetch messages as needed).
|
12
12
|
#
|
13
|
+
# Note that unlike some other messaging protocols/systems, messages are not delivered directly
|
14
|
+
# to queues. They are delivered to exchanges that route messages to queues using rules
|
15
|
+
# knows as *bindings*.
|
16
|
+
#
|
13
17
|
#
|
14
18
|
# h2. Concept of bindings
|
15
19
|
#
|
20
|
+
# Binding is an association between a queue and an exchange.
|
16
21
|
# Queues must be bound to at least one exchange in order to receive messages from publishers.
|
17
22
|
# Learn more about bindings in {Exchange Exchange class documentation}.
|
18
23
|
#
|
19
24
|
#
|
25
|
+
# h2. Key methods
|
26
|
+
#
|
27
|
+
# Key methods of Queue class are
|
28
|
+
#
|
29
|
+
# * {Queue#bind}
|
30
|
+
# * {Queue#subscribe}
|
31
|
+
# * {Queue#pop}
|
32
|
+
# * {Queue#delete}
|
33
|
+
# * {Queue#purge}
|
34
|
+
# * {Queue#unbind}
|
35
|
+
#
|
36
|
+
#
|
20
37
|
# h2. Queue names. Server-named queues. Predefined queues.
|
21
38
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
39
|
+
# Every queue has a name that identifies it. Queue names often contain several segments separated by a dot (.), similarly to how URI
|
40
|
+
# path segments are separated by a slash (/), although it may be almost any string, with some limitations (see below).
|
41
|
+
# Applications may pick queue names or ask broker to generate a name for them. To do so, pass *empty string* as queue name argument.
|
42
|
+
#
|
43
|
+
# Here is an example:
|
44
|
+
#
|
45
|
+
# @example Declaring a server-named queue using AMQP::Queue constructor
|
46
|
+
# AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
|
47
|
+
# AMQP::Channel.new do |channel, open_ok|
|
48
|
+
# AMQP::Queue.new(channel, "", :auto_delete => true) do |queue, declare_ok|
|
49
|
+
# puts "#{queue.name} is ready to go. AMQP method: #{declare_ok.inspect}"
|
50
|
+
#
|
51
|
+
# connection.close {
|
52
|
+
# EM.stop { exit }
|
53
|
+
# }
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# <script src="https://gist.github.com/939596.js?file=gistfile1.rb"></script>
|
59
|
+
#
|
60
|
+
# If you want to declare a queue with a particular name, for example, "images.resize", pass it to Queue class constructor:
|
61
|
+
#
|
62
|
+
# @example Declaring a server-named queue using AMQP::Queue constructor
|
63
|
+
# AMQP.start("amqp://guest:guest@dev.rabbitmq.com:5672/") do |connection, open_ok|
|
64
|
+
# AMQP::Channel.new do |channel, open_ok|
|
65
|
+
# AMQP::Queue.new(channel, "images.resize", :auto_delete => true) do |queue, declare_ok|
|
66
|
+
# puts "#{queue.name} is ready to go."
|
67
|
+
#
|
68
|
+
# connection.close {
|
69
|
+
# EM.stop { exit }
|
70
|
+
# }
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# <script src="https://gist.github.com/939600.js?file=gistfile1.rb"></script>
|
76
|
+
#
|
77
|
+
# Queue names starting with 'amq.' are reserved for internal use by the broker. Attempts to declare queue with a name that violates this
|
78
|
+
# rule will result in AMQP::IncompatibleOptionsError to be thrown (when
|
79
|
+
# queue is re-declared on the same channel object) or channel-level exception (when originally queue
|
80
|
+
# was declared on one channel and re-declaration with different attributes happens on another channel).
|
81
|
+
# Learn more in {file:docs/Queues.textile Queues guide} and {file:docs/ErrorHandling.textile Error Handling guide}.
|
82
|
+
#
|
25
83
|
#
|
26
|
-
# When a queue is created without a name, the server will generate a
|
27
|
-
# unique name internally (not currently supported in this library).
|
28
84
|
#
|
29
85
|
# h2. Queue life-cycles. When use of server-named queues is optimal and when it isn't.
|
30
86
|
#
|
31
87
|
# To quote AMQP 0.9.1 spec, there are two common message queue life-cycles:
|
32
88
|
#
|
33
|
-
#
|
89
|
+
# * Durable message queues that are shared by many consumers and have an independent existence: i.e. they
|
34
90
|
# will continue to exist and collect messages whether or not there are consumers to receive them.
|
35
91
|
# * Temporary message queues that are private to one consumer and are tied to that consumer. When the
|
36
92
|
# consumer disconnects, the message queue is deleted.
|
@@ -78,7 +134,7 @@ module AMQP
|
|
78
134
|
# Publishing messages as persistent affects performance (just like with data stores, durability comes at a certain cost
|
79
135
|
# in performance and vise versa). Pass :persistent => true to {Exchange#publish} to publish your message as persistent.
|
80
136
|
#
|
81
|
-
# Note that *only durable queues can be bound to durable exchanges*.
|
137
|
+
# Note that *only durable queues can be bound to durable exchanges*. Learn more in our {file:docs/Durability.textile Durability guide}.
|
82
138
|
#
|
83
139
|
#
|
84
140
|
# h2. Message ordering
|
@@ -86,16 +142,11 @@ module AMQP
|
|
86
142
|
# RabbitMQ FAQ explains {http://www.rabbitmq.com/faq.html#message-ordering ordering of messages in AMQP queues}
|
87
143
|
#
|
88
144
|
#
|
89
|
-
# h2.
|
145
|
+
# h2. Error handling
|
90
146
|
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
# * {Queue#subscribe}
|
95
|
-
# * {Queue#pop}
|
96
|
-
# * {Queue#delete}
|
97
|
-
# * {Queue#purge}
|
98
|
-
# * {Queue#unbind}
|
147
|
+
# When channel-level error occurs, queues associated with that channel are reset: internal state and callbacks
|
148
|
+
# are cleared. Recommended strategy is to open a new channel and re-declare all the entities you need.
|
149
|
+
# Learn more in {file:docs/ErrorHandling.textile Error Handling guide}.
|
99
150
|
#
|
100
151
|
#
|
101
152
|
# @note Please make sure you read a section on queue durability vs. messages
|
@@ -112,11 +163,8 @@ module AMQP
|
|
112
163
|
|
113
164
|
# Name of this queue
|
114
165
|
attr_reader :name
|
115
|
-
attr_reader :sync_bind
|
116
166
|
# Options this queue object was instantiated with
|
117
167
|
attr_accessor :opts
|
118
|
-
attr_accessor :on_declare
|
119
|
-
attr_accessor :on_bind
|
120
168
|
|
121
169
|
|
122
170
|
|
@@ -163,8 +211,14 @@ module AMQP
|
|
163
211
|
@channel = channel
|
164
212
|
name = AMQ::Protocol::EMPTY_STRING if name.nil?
|
165
213
|
@name = name unless name.empty?
|
166
|
-
@
|
167
|
-
@
|
214
|
+
@server_named = name.empty?
|
215
|
+
@opts = self.class.add_default_options(name, opts, block)
|
216
|
+
@bindings = Hash.new
|
217
|
+
|
218
|
+
# a deferrable that we use to delay operations until this queue is actually declared.
|
219
|
+
# one reason for this is to support a case when a server-named queue is immediately bound.
|
220
|
+
# it's crazy, but 0.7.x supports it, so... MK.
|
221
|
+
@declaration_deferrable = AMQ::Client::EventMachineClient::Deferrable.new
|
168
222
|
|
169
223
|
if @opts[:nowait]
|
170
224
|
@status = :opened
|
@@ -176,6 +230,8 @@ module AMQP
|
|
176
230
|
super(channel.connection, channel, name)
|
177
231
|
|
178
232
|
shim = Proc.new do |q, declare_ok|
|
233
|
+
@declaration_deferrable.succeed
|
234
|
+
|
179
235
|
case block.arity
|
180
236
|
when 1 then block.call(q)
|
181
237
|
else
|
@@ -187,11 +243,19 @@ module AMQP
|
|
187
243
|
if block
|
188
244
|
self.declare(@opts[:passive], @opts[:durable], @opts[:exclusive], @opts[:auto_delete], @opts[:nowait], @opts[:arguments], &shim)
|
189
245
|
else
|
190
|
-
|
246
|
+
injected_callback = Proc.new { @declaration_deferrable.succeed }
|
247
|
+
# we cannot pass :nowait as true here, AMQ::Client::Queue will (rightfully) raise an exception because
|
248
|
+
# it has no idea about crazy edge cases we are trying to support for sake of backwards compatibility. MK.
|
249
|
+
self.declare(@opts[:passive], @opts[:durable], @opts[:exclusive], @opts[:auto_delete], false, @opts[:arguments], &injected_callback)
|
191
250
|
end
|
192
251
|
end
|
193
252
|
end
|
194
253
|
|
254
|
+
# @return [Boolean] true if this queue is server-named
|
255
|
+
def server_named?
|
256
|
+
@server_named
|
257
|
+
end # server_named?
|
258
|
+
|
195
259
|
|
196
260
|
# This method binds a queue to an exchange. Until a queue is
|
197
261
|
# bound it will not receive any messages. In a classic messaging
|
@@ -234,14 +298,21 @@ module AMQP
|
|
234
298
|
# @see Queue#unbind
|
235
299
|
def bind(exchange, opts = {}, &block)
|
236
300
|
@status = :unbound
|
237
|
-
@sync_bind = !opts[:nowait]
|
238
301
|
# amq-client's Queue already does exchange.respond_to?(:name) ? exchange.name : exchange
|
239
302
|
# for us
|
240
303
|
exchange = exchange
|
241
304
|
@bindings[exchange] = opts
|
242
305
|
|
243
|
-
|
244
|
-
|
306
|
+
if self.server_named?
|
307
|
+
@channel.once_open do
|
308
|
+
@declaration_deferrable.callback do
|
309
|
+
super(exchange, (opts[:key] || opts[:routing_key] || AMQ::Protocol::EMPTY_STRING), (opts[:nowait] || block.nil?), opts[:arguments], &block)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
else
|
313
|
+
@channel.once_open do
|
314
|
+
super(exchange, (opts[:key] || opts[:routing_key] || AMQ::Protocol::EMPTY_STRING), (opts[:nowait] || block.nil?), opts[:arguments], &block)
|
315
|
+
end
|
245
316
|
end
|
246
317
|
|
247
318
|
self
|
@@ -599,14 +670,6 @@ module AMQP
|
|
599
670
|
@on_declare
|
600
671
|
end
|
601
672
|
|
602
|
-
# Compatibility alias for #on_bind.
|
603
|
-
#
|
604
|
-
# @api public
|
605
|
-
# @deprecated
|
606
|
-
def bind_callback
|
607
|
-
@on_bind
|
608
|
-
end
|
609
|
-
|
610
673
|
|
611
674
|
|
612
675
|
|