bunny 0.6.3.rc2 → 0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.rspec +3 -0
- data/.travis.yml +15 -0
- data/.yardopts +9 -0
- data/CHANGELOG +3 -0
- data/Gemfile +39 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +5 -4
- data/README.textile +54 -0
- data/Rakefile +15 -13
- data/bunny.gemspec +42 -61
- data/examples/simple_08.rb +4 -2
- data/examples/simple_09.rb +4 -2
- data/examples/simple_ack_08.rb +3 -1
- data/examples/simple_ack_09.rb +3 -1
- data/examples/simple_consumer_08.rb +4 -2
- data/examples/simple_consumer_09.rb +4 -2
- data/examples/simple_fanout_08.rb +3 -1
- data/examples/simple_fanout_09.rb +3 -1
- data/examples/simple_headers_08.rb +5 -3
- data/examples/simple_headers_09.rb +5 -3
- data/examples/simple_publisher_08.rb +3 -1
- data/examples/simple_publisher_09.rb +3 -1
- data/examples/simple_topic_08.rb +5 -3
- data/examples/simple_topic_09.rb +5 -3
- data/ext/amqp-0.8.json +616 -0
- data/ext/amqp-0.9.1.json +388 -0
- data/ext/config.yml +4 -0
- data/ext/qparser.rb +463 -0
- data/lib/bunny.rb +88 -66
- data/lib/bunny/channel08.rb +38 -38
- data/lib/bunny/channel09.rb +37 -37
- data/lib/bunny/client08.rb +184 -206
- data/lib/bunny/client09.rb +277 -363
- data/lib/bunny/consumer.rb +35 -0
- data/lib/bunny/exchange08.rb +37 -41
- data/lib/bunny/exchange09.rb +106 -124
- data/lib/bunny/queue08.rb +216 -202
- data/lib/bunny/queue09.rb +256 -326
- data/lib/bunny/subscription08.rb +30 -29
- data/lib/bunny/subscription09.rb +84 -83
- data/lib/bunny/version.rb +5 -0
- data/lib/qrack/amq-client-url.rb +165 -0
- data/lib/qrack/channel.rb +19 -17
- data/lib/qrack/client.rb +152 -151
- data/lib/qrack/errors.rb +5 -0
- data/lib/qrack/protocol/protocol08.rb +132 -130
- data/lib/qrack/protocol/protocol09.rb +133 -131
- data/lib/qrack/protocol/spec08.rb +2 -0
- data/lib/qrack/protocol/spec09.rb +2 -0
- data/lib/qrack/qrack08.rb +7 -10
- data/lib/qrack/qrack09.rb +7 -10
- data/lib/qrack/queue.rb +27 -40
- data/lib/qrack/subscription.rb +102 -101
- data/lib/qrack/transport/buffer08.rb +266 -264
- data/lib/qrack/transport/buffer09.rb +268 -264
- data/lib/qrack/transport/frame08.rb +13 -11
- data/lib/qrack/transport/frame09.rb +9 -7
- data/spec/spec_08/bunny_spec.rb +48 -45
- data/spec/spec_08/connection_spec.rb +10 -7
- data/spec/spec_08/exchange_spec.rb +145 -143
- data/spec/spec_08/queue_spec.rb +161 -161
- data/spec/spec_09/bunny_spec.rb +46 -44
- data/spec/spec_09/connection_spec.rb +15 -8
- data/spec/spec_09/exchange_spec.rb +147 -145
- data/spec/spec_09/queue_spec.rb +182 -184
- metadata +60 -41
- data/README.rdoc +0 -66
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
####################################
|
4
|
+
# NOTE: THIS CLASS IS HERE TO MAKE #
|
5
|
+
# TRANSITION TO AMQ CLIENT EASIER #
|
6
|
+
####################################
|
7
|
+
|
8
|
+
require "qrack/subscription"
|
9
|
+
|
10
|
+
# NOTE: This file is rather a temporary hack to fix
|
11
|
+
# https://github.com/ruby-amqp/bunny/issues/9 then
|
12
|
+
# some permanent solution. It's mostly copied from
|
13
|
+
# the AMQP and AMQ Client gems. Later on we should
|
14
|
+
# use AMQ Client directly and just inherit from
|
15
|
+
# the AMQ::Client::Sync::Consumer class.
|
16
|
+
|
17
|
+
module Bunny
|
18
|
+
|
19
|
+
# AMQP consumers are entities that handle messages delivered
|
20
|
+
# to them ("push API" as opposed to "pull API") by AMQP broker.
|
21
|
+
# Every consumer is associated with a queue. Consumers can be
|
22
|
+
# exclusive (no other consumers can be registered for the same
|
23
|
+
# queue) or not (consumers share the queue). In the case of
|
24
|
+
# multiple consumers per queue, messages are distributed in
|
25
|
+
# round robin manner with respect to channel-level prefetch
|
26
|
+
# setting).
|
27
|
+
class Consumer < Qrack::Subscription
|
28
|
+
def initialize(*args)
|
29
|
+
super(*args)
|
30
|
+
@consumer_tag ||= (1..32).to_a.shuffle.join
|
31
|
+
end
|
32
|
+
|
33
|
+
alias_method :consume, :start
|
34
|
+
end
|
35
|
+
end
|
data/lib/bunny/exchange08.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
1
3
|
module Bunny
|
2
|
-
|
4
|
+
|
3
5
|
=begin rdoc
|
4
6
|
|
5
7
|
=== DESCRIPTION:
|
@@ -28,7 +30,7 @@ target broker/server or visit the {AMQP website}[http://www.amqp.org] to find th
|
|
28
30
|
specification that applies to your target broker/server.
|
29
31
|
|
30
32
|
=end
|
31
|
-
|
33
|
+
|
32
34
|
class Exchange
|
33
35
|
|
34
36
|
attr_reader :client, :type, :name, :opts, :key
|
@@ -36,38 +38,35 @@ specification that applies to your target broker/server.
|
|
36
38
|
def initialize(client, name, opts = {})
|
37
39
|
# check connection to server
|
38
40
|
raise Bunny::ConnectionError, 'Not connected to server' if client.status == :not_connected
|
39
|
-
|
41
|
+
|
40
42
|
@client, @name, @opts = client, name, opts
|
41
|
-
|
43
|
+
|
42
44
|
# set up the exchange type catering for default names
|
43
|
-
if name
|
44
|
-
|
45
|
+
if name =~ /^amq\.(.+)$/
|
46
|
+
predeclared = true
|
47
|
+
new_type = $1
|
45
48
|
# handle 'amq.match' default
|
46
49
|
new_type = 'headers' if new_type == 'match'
|
47
50
|
@type = new_type.to_sym
|
48
51
|
else
|
49
52
|
@type = opts[:type] || :direct
|
50
53
|
end
|
51
|
-
|
54
|
+
|
52
55
|
@key = opts[:key]
|
53
56
|
@client.exchanges[@name] ||= self
|
54
|
-
|
57
|
+
|
55
58
|
# ignore the :nowait option if passed, otherwise program will hang waiting for a
|
56
59
|
# response that will not be sent by the server
|
57
60
|
opts.delete(:nowait)
|
58
|
-
|
59
|
-
unless name == "amq.#{type}" or name == ''
|
60
|
-
client.send_frame(
|
61
|
-
Qrack::Protocol::Exchange::Declare.new(
|
62
|
-
{ :exchange => name, :type => type, :nowait => false }.merge(opts)
|
63
|
-
)
|
64
|
-
)
|
65
61
|
|
66
|
-
|
62
|
+
unless predeclared or name == ''
|
63
|
+
opts = { :exchange => name, :type => type, :nowait => false }.merge(opts)
|
64
|
+
|
65
|
+
client.send_frame(Qrack::Protocol::Exchange::Declare.new(opts))
|
67
66
|
|
68
|
-
|
69
|
-
"Error declaring exchange #{name}: type = #{type}")
|
67
|
+
method = client.next_method
|
70
68
|
|
69
|
+
client.check_response(method, Qrack::Protocol::Exchange::DeclareOk, "Error declaring exchange #{name}: type = #{type}")
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
@@ -95,14 +94,11 @@ if successful. If an error occurs raises _Bunny_::_ProtocolError_.
|
|
95
94
|
# response that will not be sent by the server
|
96
95
|
opts.delete(:nowait)
|
97
96
|
|
98
|
-
client.send_frame(
|
99
|
-
Qrack::Protocol::Exchange::Delete.new({ :exchange => name, :nowait => false }.merge(opts))
|
100
|
-
)
|
97
|
+
client.send_frame(Qrack::Protocol::Exchange::Delete.new({ :exchange => name, :nowait => false }.merge(opts)))
|
101
98
|
|
102
|
-
|
99
|
+
method = client.next_method
|
103
100
|
|
104
|
-
|
105
|
-
"Error deleting exchange #{name}")
|
101
|
+
client.check_response(method, Qrack::Protocol::Exchange::DeleteOk, "Error deleting exchange #{name}")
|
106
102
|
|
107
103
|
client.exchanges.delete(name)
|
108
104
|
|
@@ -122,6 +118,7 @@ if any, is committed.
|
|
122
118
|
|
123
119
|
* <tt>:key => 'routing_key'</tt> - Specifies the routing key for the message. The routing key is
|
124
120
|
used for routing messages depending on the exchange configuration.
|
121
|
+
* <tt>:content_type => 'content/type'</tt> - Specifies the content type to use for the message.
|
125
122
|
* <tt>:mandatory => true or false (_default_)</tt> - Tells the server how to react if the message
|
126
123
|
cannot be routed to a queue. If set to _true_, the server will return an unroutable message
|
127
124
|
with a Return method. If this flag is zero, the server silently drops the message.
|
@@ -130,8 +127,8 @@ if any, is committed.
|
|
130
127
|
undeliverable message with a Return method. If set to _false_, the server will queue the message,
|
131
128
|
but with no guarantee that it will ever be consumed.
|
132
129
|
* <tt>:persistent => true or false (_default_)</tt> - Tells the server whether to persist the message
|
133
|
-
If set to _true_, the message will be persisted to disk and not lost if the server restarts.
|
134
|
-
If set to _false_, the message will not be persisted across server restart. Setting to _true_
|
130
|
+
If set to _true_, the message will be persisted to disk and not lost if the server restarts.
|
131
|
+
If set to _false_, the message will not be persisted across server restart. Setting to _true_
|
135
132
|
incurs a performance penalty as there is an extra cost associated with disk access.
|
136
133
|
|
137
134
|
==== RETURNS:
|
@@ -144,25 +141,24 @@ nil
|
|
144
141
|
opts = opts.dup
|
145
142
|
out = []
|
146
143
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
)
|
144
|
+
# Set up options
|
145
|
+
routing_key = opts.delete(:key) || key
|
146
|
+
mandatory = opts.delete(:mandatory)
|
147
|
+
immediate = opts.delete(:immediate)
|
148
|
+
delivery_mode = opts.delete(:persistent) ? 2 : 1
|
149
|
+
content_type = opts.delete(:content_type) || 'application/octet-stream'
|
150
|
+
|
151
|
+
out << Qrack::Protocol::Basic::Publish.new({ :exchange => name,
|
152
|
+
:routing_key => routing_key,
|
153
|
+
:mandatory => mandatory,
|
154
|
+
:immediate => immediate })
|
159
155
|
data = data.to_s
|
160
156
|
out << Qrack::Protocol::Header.new(
|
161
157
|
Qrack::Protocol::Basic,
|
162
158
|
data.bytesize, {
|
163
|
-
:content_type =>
|
159
|
+
:content_type => content_type,
|
164
160
|
:delivery_mode => delivery_mode,
|
165
|
-
:priority => 0
|
161
|
+
:priority => 0
|
166
162
|
}.merge(opts)
|
167
163
|
)
|
168
164
|
out << Qrack::Transport::Body.new(data)
|
@@ -171,5 +167,5 @@ nil
|
|
171
167
|
end
|
172
168
|
|
173
169
|
end
|
174
|
-
|
170
|
+
|
175
171
|
end
|
data/lib/bunny/exchange09.rb
CHANGED
@@ -1,34 +1,29 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
=begin rdoc
|
4
|
-
|
5
|
-
=== DESCRIPTION:
|
6
|
-
|
7
|
-
*Exchanges* are the routing and distribution hub of AMQP. All messages that Bunny sends
|
8
|
-
to an AMQP broker/server _have_ to pass through an exchange in order to be routed to a
|
9
|
-
destination queue. The AMQP specification defines the types of exchange that you can create.
|
10
|
-
|
11
|
-
At the time of writing there are four (4) types of exchange defined -
|
1
|
+
# encoding: utf-8
|
12
2
|
|
13
|
-
|
14
|
-
* <tt>:fanout</tt>
|
15
|
-
* <tt>:topic</tt>
|
16
|
-
* <tt>:headers</tt>
|
17
|
-
|
18
|
-
AMQP-compliant brokers/servers are required to provide default exchanges for the _direct_ and
|
19
|
-
_fanout_ exchange types. All default exchanges are prefixed with <tt>'amq.'</tt>, for example -
|
20
|
-
|
21
|
-
* <tt>amq.direct</tt>
|
22
|
-
* <tt>amq.fanout</tt>
|
23
|
-
* <tt>amq.topic</tt>
|
24
|
-
* <tt>amq.match</tt> or <tt>amq.headers</tt>
|
25
|
-
|
26
|
-
If you want more information about exchanges, please consult the documentation for your
|
27
|
-
target broker/server or visit the {AMQP website}[http://www.amqp.org] to find the version of the
|
28
|
-
specification that applies to your target broker/server.
|
3
|
+
module Bunny
|
29
4
|
|
30
|
-
|
31
|
-
|
5
|
+
# *Exchanges* are the routing and distribution hub of AMQP. All messages that Bunny sends
|
6
|
+
# to an AMQP broker/server @have_to pass through an exchange in order to be routed to a
|
7
|
+
# destination queue. The AMQP specification defines the types of exchange that you can create.
|
8
|
+
#
|
9
|
+
# At the time of writing there are four (4) types of exchange defined:
|
10
|
+
#
|
11
|
+
# * @:direct@
|
12
|
+
# * @:fanout@
|
13
|
+
# * @:topic@
|
14
|
+
# * @:headers@
|
15
|
+
#
|
16
|
+
# AMQP-compliant brokers/servers are required to provide default exchanges for the @direct@ and
|
17
|
+
# @fanout@ exchange types. All default exchanges are prefixed with @'amq.'@, for example:
|
18
|
+
#
|
19
|
+
# * @amq.direct@
|
20
|
+
# * @amq.fanout@
|
21
|
+
# * @amq.topic@
|
22
|
+
# * @amq.match@ or @amq.headers@
|
23
|
+
#
|
24
|
+
# If you want more information about exchanges, please consult the documentation for your
|
25
|
+
# target broker/server or visit the "AMQP website":http://www.amqp.org to find the version of the
|
26
|
+
# specification that applies to your target broker/server.
|
32
27
|
class Exchange09
|
33
28
|
|
34
29
|
attr_reader :client, :type, :name, :opts, :key
|
@@ -36,74 +31,63 @@ specification that applies to your target broker/server.
|
|
36
31
|
def initialize(client, name, opts = {})
|
37
32
|
# check connection to server
|
38
33
|
raise Bunny::ConnectionError, 'Not connected to server' if client.status == :not_connected
|
39
|
-
|
34
|
+
|
40
35
|
@client, @name, @opts = client, name, opts
|
41
|
-
|
36
|
+
|
42
37
|
# set up the exchange type catering for default names
|
43
|
-
if name
|
44
|
-
|
38
|
+
if name =~ /^amq\.(.+)$/
|
39
|
+
predeclared = true
|
40
|
+
new_type = $1
|
45
41
|
# handle 'amq.match' default
|
46
42
|
new_type = 'headers' if new_type == 'match'
|
47
43
|
@type = new_type.to_sym
|
48
44
|
else
|
49
45
|
@type = opts[:type] || :direct
|
50
46
|
end
|
51
|
-
|
47
|
+
|
52
48
|
@key = opts[:key]
|
53
49
|
@client.exchanges[@name] ||= self
|
54
|
-
|
50
|
+
|
55
51
|
# ignore the :nowait option if passed, otherwise program will hang waiting for a
|
56
52
|
# response that will not be sent by the server
|
57
53
|
opts.delete(:nowait)
|
58
|
-
|
59
|
-
unless
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
)
|
54
|
+
|
55
|
+
unless predeclared or name == ''
|
56
|
+
opts = {
|
57
|
+
:exchange => name, :type => type, :nowait => false,
|
58
|
+
:deprecated_ticket => 0, :deprecated_auto_delete => false, :deprecated_internal => false
|
59
|
+
}.merge(opts)
|
60
|
+
|
61
|
+
client.send_frame(Qrack::Protocol09::Exchange::Declare.new(opts))
|
66
62
|
|
67
63
|
method = client.next_method
|
68
64
|
|
69
|
-
|
70
|
-
"Error declaring exchange #{name}: type = #{type}")
|
71
|
-
|
65
|
+
client.check_response(method, Qrack::Protocol09::Exchange::DeclareOk, "Error declaring exchange #{name}: type = #{type}")
|
72
66
|
end
|
73
67
|
end
|
74
68
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
delete the exchange if it has no queue bindings. If the exchange has queue bindings the
|
86
|
-
server does not delete it but raises a channel exception instead.
|
87
|
-
* <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
|
88
|
-
|
89
|
-
==== Returns:
|
90
|
-
|
91
|
-
<tt>:delete_ok</tt> if successful
|
92
|
-
=end
|
93
|
-
|
69
|
+
# Requests that an exchange is deleted from broker/server. Removes reference from exchanges
|
70
|
+
# if successful. If an error occurs raises {Bunny::ProtocolError}.
|
71
|
+
#
|
72
|
+
# @option opts [Boolean] :if_unused (false)
|
73
|
+
# If set to @true@, the server will only delete the exchange if it has no queue bindings. If the exchange has queue bindings the server does not delete it but raises a channel exception instead.
|
74
|
+
#
|
75
|
+
# @option opts [Boolean] :nowait (false)
|
76
|
+
# Ignored by Bunny, always @false@.
|
77
|
+
#
|
78
|
+
# @return [Symbol] @:delete_ok@ if successful.
|
94
79
|
def delete(opts = {})
|
95
80
|
# ignore the :nowait option if passed, otherwise program will hang waiting for a
|
96
81
|
# response that will not be sent by the server
|
97
82
|
opts.delete(:nowait)
|
98
83
|
|
99
|
-
|
100
|
-
|
101
|
-
)
|
84
|
+
opts = { :exchange => name, :nowait => false, :deprecated_ticket => 0 }.merge(opts)
|
85
|
+
|
86
|
+
client.send_frame(Qrack::Protocol09::Exchange::Delete.new(opts))
|
102
87
|
|
103
88
|
method = client.next_method
|
104
89
|
|
105
|
-
|
106
|
-
"Error deleting exchange #{name}")
|
90
|
+
client.check_response(method, Qrack::Protocol09::Exchange::DeleteOk, "Error deleting exchange #{name}")
|
107
91
|
|
108
92
|
client.exchanges.delete(name)
|
109
93
|
|
@@ -111,67 +95,65 @@ if successful. If an error occurs raises _Bunny_::_ProtocolError_.
|
|
111
95
|
:delete_ok
|
112
96
|
end
|
113
97
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
98
|
+
# Publishes a message to a specific exchange. The message will be routed to queues as defined
|
99
|
+
# by the exchange configuration and distributed to any active consumers when the transaction,
|
100
|
+
# if any, is committed.
|
101
|
+
#
|
102
|
+
# @option opts [String] :key
|
103
|
+
# Specifies the routing key for the message. The routing key is
|
104
|
+
# used for routing messages depending on the exchange configuration.
|
105
|
+
#
|
106
|
+
# @option opts [String] :content_type
|
107
|
+
# Specifies the content type for the message.
|
108
|
+
#
|
109
|
+
# @option opts [Boolean] :mandatory (false)
|
110
|
+
# Tells the server how to react if the message cannot be routed to a queue.
|
111
|
+
# If set to @true@, the server will return an unroutable message
|
112
|
+
# with a Return method. If this flag is zero, the server silently drops the message.
|
113
|
+
#
|
114
|
+
# @option opts [Boolean] :immediate (false)
|
115
|
+
# Tells the server how to react if the message cannot be routed to a queue consumer
|
116
|
+
# immediately. If set to @true@, the server will return an undeliverable message with
|
117
|
+
# a Return method. If set to @false@, the server will queue the message, but with no
|
118
|
+
# guarantee that it will ever be consumed.
|
119
|
+
#
|
120
|
+
# @option opts [Boolean] :persistent (false)
|
121
|
+
# Tells the server whether to persist the message. If set to @true@, the message will
|
122
|
+
# be persisted to disk and not lost if the server restarts. If set to @false@, the message
|
123
|
+
# will not be persisted across server restart. Setting to @true@ incurs a performance penalty
|
124
|
+
# as there is an extra cost associated with disk access.
|
125
|
+
#
|
126
|
+
# @return [NilClass] nil
|
144
127
|
def publish(data, opts = {})
|
145
128
|
opts = opts.dup
|
146
129
|
out = []
|
147
130
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
out << Qrack::Transport09::Body.new(data)
|
131
|
+
# Set up options
|
132
|
+
routing_key = opts.delete(:key) || key
|
133
|
+
mandatory = opts.delete(:mandatory)
|
134
|
+
immediate = opts.delete(:immediate)
|
135
|
+
delivery_mode = opts.delete(:persistent) ? 2 : 1
|
136
|
+
content_type = opts.delete(:content_type) || 'application/octet-stream'
|
137
|
+
|
138
|
+
out << Qrack::Protocol09::Basic::Publish.new({ :exchange => name,
|
139
|
+
:routing_key => routing_key,
|
140
|
+
:mandatory => mandatory,
|
141
|
+
:immediate => immediate,
|
142
|
+
:deprecated_ticket => 0 })
|
143
|
+
data = data.to_s
|
144
|
+
out << Qrack::Protocol09::Header.new(
|
145
|
+
Qrack::Protocol09::Basic,
|
146
|
+
data.bytesize, {
|
147
|
+
:content_type => content_type,
|
148
|
+
:delivery_mode => delivery_mode,
|
149
|
+
:priority => 0
|
150
|
+
}.merge(opts)
|
151
|
+
)
|
152
|
+
out << Qrack::Transport09::Body.new(data)
|
171
153
|
|
172
154
|
client.send_frame(*out)
|
173
155
|
end
|
174
156
|
|
175
157
|
end
|
176
|
-
|
158
|
+
|
177
159
|
end
|