bunny 0.7.12 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/.gitignore +2 -2
  2. data/.travis.yml +7 -16
  3. data/CHANGELOG +3 -21
  4. data/Gemfile +2 -4
  5. data/README.textile +31 -9
  6. data/Rakefile +3 -3
  7. data/bunny.gemspec +6 -3
  8. data/examples/{simple_08.rb → simple.rb} +1 -1
  9. data/examples/{simple_ack_08.rb → simple_ack.rb} +1 -1
  10. data/examples/{simple_consumer_08.rb → simple_consumer.rb} +4 -4
  11. data/examples/{simple_fanout_08.rb → simple_fanout.rb} +1 -1
  12. data/examples/{simple_headers_08.rb → simple_headers.rb} +2 -2
  13. data/examples/{simple_publisher_09.rb → simple_publisher.rb} +1 -1
  14. data/examples/{simple_topic_09.rb → simple_topic.rb} +2 -2
  15. data/ext/amqp-0.9.1.json +1 -0
  16. data/ext/config.yml +3 -3
  17. data/ext/qparser.rb +9 -52
  18. data/lib/bunny.rb +15 -33
  19. data/lib/bunny/{channel08.rb → channel.rb} +0 -0
  20. data/lib/bunny/{client09.rb → client.rb} +34 -46
  21. data/lib/bunny/{exchange09.rb → exchange.rb} +16 -15
  22. data/lib/bunny/{queue09.rb → queue.rb} +26 -23
  23. data/lib/bunny/{subscription09.rb → subscription.rb} +11 -6
  24. data/lib/bunny/version.rb +1 -1
  25. data/lib/qrack/client.rb +30 -21
  26. data/lib/qrack/protocol/{protocol08.rb → protocol.rb} +2 -1
  27. data/lib/qrack/protocol/{spec09.rb → spec.rb} +8 -7
  28. data/lib/qrack/{qrack08.rb → qrack.rb} +4 -4
  29. data/lib/qrack/subscription.rb +58 -9
  30. data/lib/qrack/transport/{buffer08.rb → buffer.rb} +8 -0
  31. data/lib/qrack/transport/{frame08.rb → frame.rb} +7 -22
  32. data/spec/spec_09/bunny_spec.rb +10 -8
  33. data/spec/spec_09/connection_spec.rb +8 -3
  34. data/spec/spec_09/exchange_spec.rb +22 -19
  35. data/spec/spec_09/queue_spec.rb +32 -18
  36. metadata +69 -76
  37. checksums.yaml +0 -7
  38. data/examples/simple_09.rb +0 -32
  39. data/examples/simple_ack_09.rb +0 -35
  40. data/examples/simple_consumer_09.rb +0 -55
  41. data/examples/simple_fanout_09.rb +0 -41
  42. data/examples/simple_headers_09.rb +0 -42
  43. data/examples/simple_publisher_08.rb +0 -29
  44. data/examples/simple_topic_08.rb +0 -61
  45. data/ext/amqp-0.8.json +0 -616
  46. data/lib/bunny/channel09.rb +0 -39
  47. data/lib/bunny/client08.rb +0 -480
  48. data/lib/bunny/exchange08.rb +0 -177
  49. data/lib/bunny/queue08.rb +0 -403
  50. data/lib/bunny/subscription08.rb +0 -87
  51. data/lib/qrack/protocol/protocol09.rb +0 -135
  52. data/lib/qrack/protocol/spec08.rb +0 -828
  53. data/lib/qrack/qrack09.rb +0 -20
  54. data/lib/qrack/transport/buffer09.rb +0 -305
  55. data/lib/qrack/transport/frame09.rb +0 -97
  56. data/spec/spec_08/bunny_spec.rb +0 -75
  57. data/spec/spec_08/connection_spec.rb +0 -24
  58. data/spec/spec_08/exchange_spec.rb +0 -170
  59. data/spec/spec_08/queue_spec.rb +0 -239
@@ -1,177 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Bunny
4
-
5
- =begin rdoc
6
-
7
- === DESCRIPTION:
8
-
9
- *Exchanges* are the routing and distribution hub of AMQP. All messages that Bunny sends
10
- to an AMQP broker/server _have_ to pass through an exchange in order to be routed to a
11
- destination queue. The AMQP specification defines the types of exchange that you can create.
12
-
13
- At the time of writing there are four (4) types of exchange defined -
14
-
15
- * <tt>:direct</tt>
16
- * <tt>:fanout</tt>
17
- * <tt>:topic</tt>
18
- * <tt>:headers</tt>
19
-
20
- AMQP-compliant brokers/servers are required to provide default exchanges for the _direct_ and
21
- _fanout_ exchange types. All default exchanges are prefixed with <tt>'amq.'</tt>, for example -
22
-
23
- * <tt>amq.direct</tt>
24
- * <tt>amq.fanout</tt>
25
- * <tt>amq.topic</tt>
26
- * <tt>amq.match</tt> or <tt>amq.headers</tt>
27
-
28
- If you want more information about exchanges, please consult the documentation for your
29
- target broker/server or visit the {AMQP website}[http://www.amqp.org] to find the version of the
30
- specification that applies to your target broker/server.
31
-
32
- =end
33
-
34
- class Exchange
35
-
36
- attr_reader :client, :type, :name, :opts, :key
37
-
38
- def initialize(client, name, opts = {})
39
- # check connection to server
40
- raise Bunny::ConnectionError, 'Not connected to server' if client.status == :not_connected
41
-
42
- @client, @name, @opts = client, name, opts
43
-
44
- # set up the exchange type catering for default names
45
- if name =~ /^amq\.(.+)$/
46
- predeclared = true
47
- new_type = $1
48
- # handle 'amq.match' default
49
- new_type = 'headers' if new_type == 'match'
50
- @type = new_type.to_sym
51
- else
52
- @type = opts[:type] || :direct
53
- end
54
-
55
- @key = opts[:key]
56
- @client.exchanges[@name] ||= self
57
-
58
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
59
- # response that will not be sent by the server
60
- opts.delete(:nowait)
61
-
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))
66
-
67
- method = client.next_method
68
-
69
- client.check_response(method, Qrack::Protocol::Exchange::DeclareOk, "Error declaring exchange #{name}: type = #{type}")
70
- end
71
- end
72
-
73
- =begin rdoc
74
-
75
- === DESCRIPTION:
76
-
77
- Requests that an exchange is deleted from broker/server. Removes reference from exchanges
78
- if successful. If an error occurs raises _Bunny_::_ProtocolError_.
79
-
80
- ==== Options:
81
-
82
- * <tt>:if_unused => true or false (_default_)</tt> - If set to _true_, the server will only
83
- delete the exchange if it has no queue bindings. If the exchange has queue bindings the
84
- server does not delete it but raises a channel exception instead.
85
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
86
-
87
- ==== Returns:
88
-
89
- <tt>:delete_ok</tt> if successful
90
- =end
91
-
92
- def delete(opts = {})
93
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
94
- # response that will not be sent by the server
95
- opts.delete(:nowait)
96
-
97
- client.send_frame(Qrack::Protocol::Exchange::Delete.new({ :exchange => name, :nowait => false }.merge(opts)))
98
-
99
- method = client.next_method
100
-
101
- client.check_response(method, Qrack::Protocol::Exchange::DeleteOk, "Error deleting exchange #{name}")
102
-
103
- client.exchanges.delete(name)
104
-
105
- # return confirmation
106
- :delete_ok
107
- end
108
-
109
- =begin rdoc
110
-
111
- === DESCRIPTION:
112
-
113
- Publishes a message to a specific exchange. The message will be routed to queues as defined
114
- by the exchange configuration and distributed to any active consumers when the transaction,
115
- if any, is committed.
116
-
117
- ==== OPTIONS:
118
-
119
- * <tt>:key => 'routing_key'</tt> - Specifies the routing key for the message. The routing key is
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.
122
- * <tt>:mandatory => true or false (_default_)</tt> - Tells the server how to react if the message
123
- cannot be routed to a queue. If set to _true_, the server will return an unroutable message
124
- with a Return method. If this flag is zero, the server silently drops the message.
125
- * <tt>:immediate => true or false (_default_)</tt> - Tells the server how to react if the message
126
- cannot be routed to a queue consumer immediately. If set to _true_, the server will return an
127
- undeliverable message with a Return method. If set to _false_, the server will queue the message,
128
- but with no guarantee that it will ever be consumed.
129
- * <tt>:persistent => true or false (_default_)</tt> - Tells the server whether to persist the message
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_
132
- incurs a performance penalty as there is an extra cost associated with disk access.
133
-
134
- ==== RETURNS:
135
-
136
- nil
137
-
138
- =end
139
-
140
- def publish(data, opts = {})
141
- opts = opts.dup
142
- out = []
143
-
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 })
155
- data = data.to_s
156
- out << Qrack::Protocol::Header.new(
157
- Qrack::Protocol::Basic,
158
- data.bytesize, {
159
- :content_type => content_type,
160
- :delivery_mode => delivery_mode,
161
- :priority => 0
162
- }.merge(opts)
163
- )
164
-
165
- limit = @client.frame_max - 8
166
- i = 0
167
- while i < data.bytesize
168
- out << Qrack::Transport::Body.new(data.byteslice(i, limit))
169
- i += limit
170
- end
171
-
172
- client.send_frame(*out)
173
- end
174
-
175
- end
176
-
177
- end
@@ -1,403 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Bunny
4
-
5
- =begin rdoc
6
-
7
- === DESCRIPTION:
8
-
9
- Queues store and forward messages. Queues can be configured in the server or created at runtime.
10
- Queues must be attached to at least one exchange in order to receive messages from publishers.
11
-
12
- =end
13
-
14
- class Queue < Qrack::Queue
15
-
16
- def initialize(client, name, opts = {})
17
- # check connection to server
18
- raise Bunny::ConnectionError, 'Not connected to server' if client.status == :not_connected
19
-
20
- @client = client
21
- @opts = opts
22
- @delivery_tag = nil
23
- @subscription = nil
24
-
25
- # Queues without a given name are named by the server and are generally
26
- # bound to the process that created them.
27
- if !name
28
- opts = {
29
- :passive => false,
30
- :durable => false,
31
- :exclusive => true,
32
- :auto_delete => true
33
- }.merge(opts)
34
- end
35
-
36
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
37
- # response that will not be sent by the server
38
- opts.delete(:nowait)
39
-
40
- opts = { :queue => name || '', :nowait => false }.merge(opts)
41
-
42
- client.send_frame(Qrack::Protocol::Queue::Declare.new(opts))
43
-
44
- method = client.next_method
45
-
46
- client.check_response(method, Qrack::Protocol::Queue::DeclareOk, "Error declaring queue #{name}")
47
-
48
- @name = method.queue
49
- client.queues[@name] = self
50
- end
51
-
52
- # @return [Bunny::Consumer] Default consumer associated with this queue (if any), or nil
53
- # @note Default consumer is the one registered with the convenience {Bunny::Queue#subscribe} method. It has no special properties of any kind.
54
- # @see Queue#subscribe
55
- # @see Bunny::Consumer
56
- # @api public
57
- def default_consumer
58
- @default_consumer
59
- end
60
-
61
-
62
- # @return [Class]
63
- # @private
64
- def self.consumer_class
65
- # Bunny::Consumer
66
- Bunny::Subscription
67
- end # self.consumer_class
68
-
69
- =begin rdoc
70
-
71
- === DESCRIPTION:
72
-
73
- Acknowledges one or more messages delivered via the _Deliver_ or _Get_-_Ok_ methods. The client can
74
- ask to confirm a single message or a set of messages up to and including a specific message.
75
-
76
- ==== OPTIONS:
77
-
78
- * <tt>:delivery_tag</tt>
79
- * <tt>:multiple => true or false (_default_)</tt> - If set to _true_, the delivery tag is treated
80
- as "up to and including", so that the client can acknowledge multiple messages with a single
81
- method. If set to _false_, the delivery tag refers to a single message. If the multiple field
82
- is _true_, and the delivery tag is zero, tells the server to acknowledge all outstanding messages.
83
-
84
- =end
85
-
86
- def ack(opts={})
87
- # Set delivery tag
88
- if delivery_tag.nil? and opts[:delivery_tag].nil?
89
- raise Bunny::AcknowledgementError, "No delivery tag received"
90
- else
91
- self.delivery_tag = opts[:delivery_tag] if delivery_tag.nil?
92
- end
93
-
94
- opts = {:delivery_tag => delivery_tag, :multiple => false}.merge(opts)
95
-
96
- client.send_frame(Qrack::Protocol::Basic::Ack.new(opts))
97
-
98
- # reset delivery tag
99
- self.delivery_tag = nil
100
- end
101
-
102
- =begin rdoc
103
-
104
- === DESCRIPTION:
105
-
106
- Binds a queue to an exchange. Until a queue is bound it will not receive any messages. Queues are
107
- bound to the direct exchange '' by default. If error occurs, a _Bunny_::_ProtocolError_ is raised.
108
-
109
- * <tt>:key => 'routing key'* <tt>:key => 'routing_key'</tt> - Specifies the routing key for
110
- the binding. The routing key is used for routing messages depending on the exchange configuration.
111
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
112
-
113
- ==== RETURNS:
114
-
115
- <tt>:bind_ok</tt> if successful.
116
-
117
- =end
118
-
119
- def bind(exchange, opts = {})
120
- exchange = exchange.respond_to?(:name) ? exchange.name : exchange
121
-
122
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
123
- # response that will not be sent by the server
124
- opts.delete(:nowait)
125
-
126
- opts = {
127
- :queue => name,
128
- :exchange => exchange,
129
- :routing_key => opts.delete(:key),
130
- :nowait => false
131
- }.merge(opts)
132
-
133
- client.send_frame(Qrack::Protocol::Queue::Bind.new(opts))
134
-
135
- method = client.next_method
136
-
137
- client.check_response(method, Qrack::Protocol::Queue::BindOk, "Error binding queue: #{name} to exchange: #{exchange}")
138
-
139
- # return message
140
- :bind_ok
141
- end
142
-
143
- =begin rdoc
144
-
145
- === DESCRIPTION:
146
-
147
- Requests that a queue is deleted from broker/server. When a queue is deleted any pending messages
148
- are sent to a dead-letter queue if this is defined in the server configuration. Removes reference
149
- from queues if successful. If an error occurs raises _Bunny_::_ProtocolError_.
150
-
151
- ==== Options:
152
-
153
- * <tt>:if_unused => true or false (_default_)</tt> - If set to _true_, the server will only
154
- delete the queue if it has no consumers. If the queue has consumers the server does not
155
- delete it but raises a channel exception instead.
156
- * <tt>:if_empty => true or false (_default_)</tt> - If set to _true_, the server will only
157
- delete the queue if it has no messages. If the queue is not empty the server raises a channel
158
- exception.
159
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
160
-
161
- ==== Returns:
162
-
163
- <tt>:delete_ok</tt> if successful
164
- =end
165
-
166
- def delete(opts = {})
167
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
168
- # response that will not be sent by the server
169
- opts.delete(:nowait)
170
-
171
- opts = { :queue => name, :nowait => false }.merge(opts)
172
-
173
- client.send_frame(Qrack::Protocol::Queue::Delete.new(opts))
174
-
175
- method = client.next_method
176
-
177
- client.check_response(method, Qrack::Protocol::Queue::DeleteOk, "Error deleting queue #{name}")
178
-
179
- client.queues.delete(name)
180
-
181
- # return confirmation
182
- :delete_ok
183
- end
184
-
185
- =begin rdoc
186
-
187
- === DESCRIPTION:
188
-
189
- Gets a message from a queue in a synchronous way. If error occurs, raises _Bunny_::_ProtocolError_.
190
-
191
- ==== OPTIONS:
192
-
193
- * <tt>:ack => false (_default_) or true</tt> - If set to _false_, the server does not expect an
194
- acknowledgement message from the client. If set to _true_, the server expects an acknowledgement
195
- message from the client and will re-queue the message if it does not receive one within a time specified
196
- by the server.
197
-
198
- ==== RETURNS:
199
-
200
- Hash <tt>{:header, :payload, :delivery_details}</tt>. <tt>:delivery_details</tt> is
201
- a hash <tt>{:consumer_tag, :delivery_tag, :redelivered, :exchange, :routing_key}</tt>.
202
-
203
- If the queue is empty the returned hash will contain the values -
204
-
205
- :header => nil
206
- :payload => :queue_empty
207
- :delivery_details => nil
208
-
209
- N.B. If a block is provided then the hash will be passed into the block and the return value
210
- will be nil.
211
-
212
- =end
213
-
214
- def pop(opts = {}, &blk)
215
-
216
- # do we want to have to provide an acknowledgement?
217
- ack = opts.delete(:ack)
218
-
219
- opts = {
220
- :queue => name,
221
- :consumer_tag => name,
222
- :no_ack => !ack,
223
- :nowait => true
224
- }.merge(opts)
225
-
226
- client.send_frame(Qrack::Protocol::Basic::Get.new(opts))
227
-
228
- method = client.next_method
229
-
230
- if method.is_a?(Qrack::Protocol::Basic::GetEmpty) then
231
- queue_empty = true
232
- elsif !method.is_a?(Qrack::Protocol::Basic::GetOk)
233
- raise Bunny::ProtocolError, "Error getting message from queue #{name}"
234
- end
235
-
236
- if !queue_empty
237
- # get delivery tag to use for acknowledge
238
- self.delivery_tag = method.delivery_tag if ack
239
-
240
- header = client.next_payload
241
-
242
- # If maximum frame size is smaller than message payload body then message
243
- # will have a message header and several message bodies
244
- msg = ''
245
- while msg.length < header.size
246
- msg << client.next_payload
247
- end
248
-
249
- msg_hash = {:header => header, :payload => msg, :delivery_details => method.arguments}
250
-
251
- else
252
- msg_hash = {:header => nil, :payload => :queue_empty, :delivery_details => nil}
253
- end
254
-
255
- # Pass message hash to block or return message hash
256
- blk ? blk.call(msg_hash) : msg_hash
257
- end
258
-
259
- =begin rdoc
260
-
261
- === DESCRIPTION:
262
-
263
- Removes all messages from a queue. It does not cancel consumers. Purged messages are deleted
264
- without any formal "undo" mechanism. If an error occurs raises _Bunny_::_ProtocolError_.
265
-
266
- ==== Options:
267
-
268
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
269
-
270
- ==== Returns:
271
-
272
- <tt>:purge_ok</tt> if successful
273
- =end
274
-
275
- def purge(opts = {})
276
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
277
- # response that will not be sent by the server
278
- opts.delete(:nowait)
279
-
280
- opts = { :queue => name, :nowait => false }.merge(opts)
281
-
282
- client.send_frame(Qrack::Protocol::Queue::Purge.new(opts))
283
-
284
- method = client.next_method
285
-
286
- client.check_response(method, Qrack::Protocol::Queue::PurgeOk, "Error purging queue #{name}")
287
-
288
- # return confirmation
289
- :purge_ok
290
- end
291
-
292
- =begin rdoc
293
-
294
- === DESCRIPTION:
295
-
296
- Returns hash {:message_count, :consumer_count}.
297
-
298
- =end
299
-
300
- def status
301
- client.send_frame(Qrack::Protocol::Queue::Declare.new(:queue => name, :passive => true))
302
- method = client.next_method
303
- {:message_count => method.message_count, :consumer_count => method.consumer_count}
304
- end
305
-
306
- def subscribe(opts = {}, &blk)
307
- raise RuntimeError.new("This queue already has default consumer. Please instantiate Bunny::Consumer directly and call its #consume method to register additional consumers.") if @default_consumer && ! opts[:consumer_tag]
308
-
309
- # Create a subscription.
310
- @default_consumer = self.class.consumer_class.new(client, self, opts)
311
- @default_consumer.consume(&blk)
312
- end
313
-
314
- =begin rdoc
315
-
316
- === DESCRIPTION:
317
-
318
- Cancels a consumer. This does not affect already delivered messages, but it does mean
319
- the server will not send any more messages for that consumer.
320
-
321
- ==== OPTIONS:
322
-
323
- * <tt>:consumer_tag => '_tag_'</tt> - Specifies the identifier for the consumer.
324
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
325
-
326
- ==== Returns:
327
-
328
- <tt>:unsubscribe_ok</tt> if successful
329
-
330
- =end
331
-
332
- def unsubscribe(opts = {})
333
- # Default consumer_tag from subscription if not passed in
334
- consumer_tag = @default_consumer ? @default_consumer.consumer_tag : opts[:consumer_tag]
335
-
336
- # Must have consumer tag to tell server what to unsubscribe
337
- raise Bunny::UnsubscribeError,
338
- "No consumer tag received" if !consumer_tag
339
-
340
- # Cancel consumer
341
- client.send_frame(Qrack::Protocol::Basic::Cancel.new(:consumer_tag => consumer_tag,:nowait => false))
342
-
343
- method = client.next_method
344
-
345
- client.check_response(method, Qrack::Protocol::Basic::CancelOk, "Error unsubscribing from queue #{name}")
346
-
347
- # Reset subscription
348
- @default_consumer = nil
349
-
350
- # Return confirmation
351
- :unsubscribe_ok
352
- end
353
-
354
- =begin rdoc
355
-
356
- === DESCRIPTION:
357
-
358
- Removes a queue binding from an exchange. If error occurs, a _Bunny_::_ProtocolError_ is raised.
359
-
360
- ==== OPTIONS:
361
- * <tt>:key => 'routing key'* <tt>:key => 'routing_key'</tt> - Specifies the routing key for
362
- the binding.
363
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
364
-
365
- ==== RETURNS:
366
-
367
- <tt>:unbind_ok</tt> if successful.
368
-
369
- =end
370
-
371
- def unbind(exchange, opts = {})
372
- exchange = exchange.respond_to?(:name) ? exchange.name : exchange
373
-
374
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
375
- # response that will not be sent by the server
376
- opts.delete(:nowait)
377
-
378
- opts = {
379
- :queue => name,
380
- :exchange => exchange,
381
- :routing_key => opts.delete(:key),
382
- :nowait => false
383
- }.merge(opts)
384
-
385
- client.send_frame(Qrack::Protocol::Queue::Unbind.new(opts))
386
-
387
- method = client.next_method
388
-
389
- client.check_response(method, Qrack::Protocol::Queue::UnbindOk, "Error unbinding queue #{name}")
390
-
391
- # return message
392
- :unbind_ok
393
- end
394
-
395
- private
396
-
397
- def exchange
398
- @exchange ||= Bunny::Exchange.new(client, '', {:type => :direct, :key => name})
399
- end
400
-
401
- end
402
-
403
- end