bunny 0.6.3.rc2 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +15 -0
  4. data/.yardopts +9 -0
  5. data/CHANGELOG +3 -0
  6. data/Gemfile +39 -0
  7. data/Gemfile.lock +34 -0
  8. data/LICENSE +5 -4
  9. data/README.textile +54 -0
  10. data/Rakefile +15 -13
  11. data/bunny.gemspec +42 -61
  12. data/examples/simple_08.rb +4 -2
  13. data/examples/simple_09.rb +4 -2
  14. data/examples/simple_ack_08.rb +3 -1
  15. data/examples/simple_ack_09.rb +3 -1
  16. data/examples/simple_consumer_08.rb +4 -2
  17. data/examples/simple_consumer_09.rb +4 -2
  18. data/examples/simple_fanout_08.rb +3 -1
  19. data/examples/simple_fanout_09.rb +3 -1
  20. data/examples/simple_headers_08.rb +5 -3
  21. data/examples/simple_headers_09.rb +5 -3
  22. data/examples/simple_publisher_08.rb +3 -1
  23. data/examples/simple_publisher_09.rb +3 -1
  24. data/examples/simple_topic_08.rb +5 -3
  25. data/examples/simple_topic_09.rb +5 -3
  26. data/ext/amqp-0.8.json +616 -0
  27. data/ext/amqp-0.9.1.json +388 -0
  28. data/ext/config.yml +4 -0
  29. data/ext/qparser.rb +463 -0
  30. data/lib/bunny.rb +88 -66
  31. data/lib/bunny/channel08.rb +38 -38
  32. data/lib/bunny/channel09.rb +37 -37
  33. data/lib/bunny/client08.rb +184 -206
  34. data/lib/bunny/client09.rb +277 -363
  35. data/lib/bunny/consumer.rb +35 -0
  36. data/lib/bunny/exchange08.rb +37 -41
  37. data/lib/bunny/exchange09.rb +106 -124
  38. data/lib/bunny/queue08.rb +216 -202
  39. data/lib/bunny/queue09.rb +256 -326
  40. data/lib/bunny/subscription08.rb +30 -29
  41. data/lib/bunny/subscription09.rb +84 -83
  42. data/lib/bunny/version.rb +5 -0
  43. data/lib/qrack/amq-client-url.rb +165 -0
  44. data/lib/qrack/channel.rb +19 -17
  45. data/lib/qrack/client.rb +152 -151
  46. data/lib/qrack/errors.rb +5 -0
  47. data/lib/qrack/protocol/protocol08.rb +132 -130
  48. data/lib/qrack/protocol/protocol09.rb +133 -131
  49. data/lib/qrack/protocol/spec08.rb +2 -0
  50. data/lib/qrack/protocol/spec09.rb +2 -0
  51. data/lib/qrack/qrack08.rb +7 -10
  52. data/lib/qrack/qrack09.rb +7 -10
  53. data/lib/qrack/queue.rb +27 -40
  54. data/lib/qrack/subscription.rb +102 -101
  55. data/lib/qrack/transport/buffer08.rb +266 -264
  56. data/lib/qrack/transport/buffer09.rb +268 -264
  57. data/lib/qrack/transport/frame08.rb +13 -11
  58. data/lib/qrack/transport/frame09.rb +9 -7
  59. data/spec/spec_08/bunny_spec.rb +48 -45
  60. data/spec/spec_08/connection_spec.rb +10 -7
  61. data/spec/spec_08/exchange_spec.rb +145 -143
  62. data/spec/spec_08/queue_spec.rb +161 -161
  63. data/spec/spec_09/bunny_spec.rb +46 -44
  64. data/spec/spec_09/connection_spec.rb +15 -8
  65. data/spec/spec_09/exchange_spec.rb +147 -145
  66. data/spec/spec_09/queue_spec.rb +182 -184
  67. metadata +60 -41
  68. 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
@@ -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.match(/^amq\./)
44
- new_type = name.sub(/amq\./, '')
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
- method = client.next_method
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
- client.check_response(method, Qrack::Protocol::Exchange::DeclareOk,
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
- method = client.next_method
99
+ method = client.next_method
103
100
 
104
- client.check_response(method, Qrack::Protocol::Exchange::DeleteOk,
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
- # Set up options
148
- routing_key = opts.delete(:key) || key
149
- mandatory = opts.delete(:mandatory)
150
- immediate = opts.delete(:immediate)
151
- delivery_mode = opts.delete(:persistent) ? 2 : 1
152
-
153
- out << Qrack::Protocol::Basic::Publish.new(
154
- { :exchange => name,
155
- :routing_key => routing_key,
156
- :mandatory => mandatory,
157
- :immediate => immediate }
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 => 'application/octet-stream',
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
@@ -1,34 +1,29 @@
1
- module Bunny
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
- * <tt>:direct</tt>
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
- =end
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.match(/^amq\./)
44
- new_type = name.sub(/amq\./, '')
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 name == "amq.#{type}" or name == ''
60
- client.send_frame(
61
- Qrack::Protocol09::Exchange::Declare.new(
62
- { :exchange => name, :type => type, :nowait => false,
63
- :deprecated_ticket => 0, :deprecated_auto_delete => false, :deprecated_internal => false }.merge(opts)
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
- client.check_response(method, Qrack::Protocol09::Exchange::DeclareOk,
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
- =begin rdoc
76
-
77
- === DESCRIPTION:
78
-
79
- Requests that an exchange is deleted from broker/server. Removes reference from exchanges
80
- if successful. If an error occurs raises _Bunny_::_ProtocolError_.
81
-
82
- ==== Options:
83
-
84
- * <tt>:if_unused => true or false (_default_)</tt> - If set to _true_, the server will only
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
- client.send_frame(
100
- Qrack::Protocol09::Exchange::Delete.new({ :exchange => name, :nowait => false, :deprecated_ticket => 0 }.merge(opts))
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
- client.check_response(method, Qrack::Protocol09::Exchange::DeleteOk,
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
- =begin rdoc
115
-
116
- === DESCRIPTION:
117
-
118
- Publishes a message to a specific exchange. The message will be routed to queues as defined
119
- by the exchange configuration and distributed to any active consumers when the transaction,
120
- if any, is committed.
121
-
122
- ==== OPTIONS:
123
-
124
- * <tt>:key => 'routing_key'</tt> - Specifies the routing key for the message. The routing key is
125
- used for routing messages depending on the exchange configuration.
126
- * <tt>:mandatory => true or false (_default_)</tt> - Tells the server how to react if the message
127
- cannot be routed to a queue. If set to _true_, the server will return an unroutable message
128
- with a Return method. If this flag is zero, the server silently drops the message.
129
- * <tt>:immediate => true or false (_default_)</tt> - Tells the server how to react if the message
130
- cannot be routed to a queue consumer immediately. If set to _true_, the server will return an
131
- undeliverable message with a Return method. If set to _false_, the server will queue the message,
132
- but with no guarantee that it will ever be consumed.
133
- * <tt>:persistent => true or false (_default_)</tt> - Tells the server whether to persist the message
134
- If set to _true_, the message will be persisted to disk and not lost if the server restarts.
135
- If set to _false_, the message will not be persisted across server restart. Setting to _true_
136
- incurs a performance penalty as there is an extra cost associated with disk access.
137
-
138
- ==== RETURNS:
139
-
140
- nil
141
-
142
- =end
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
- # Set up options
149
- routing_key = opts.delete(:key) || key
150
- mandatory = opts.delete(:mandatory)
151
- immediate = opts.delete(:immediate)
152
- delivery_mode = opts.delete(:persistent) ? 2 : 1
153
-
154
- out << Qrack::Protocol09::Basic::Publish.new(
155
- { :exchange => name,
156
- :routing_key => routing_key,
157
- :mandatory => mandatory,
158
- :immediate => immediate,
159
- :deprecated_ticket => 0 }
160
- )
161
- data = data.to_s
162
- out << Qrack::Protocol09::Header.new(
163
- Qrack::Protocol09::Basic,
164
- data.bytesize, {
165
- :content_type => 'application/octet-stream',
166
- :delivery_mode => delivery_mode,
167
- :priority => 0
168
- }.merge(opts)
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