bunny 0.6.3.rc2 → 0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,5 +1,7 @@
1
+ # encoding: utf-8
2
+
1
3
  module Bunny
2
-
4
+
3
5
  =begin rdoc
4
6
 
5
7
  === DESCRIPTION:
@@ -9,14 +11,14 @@ Queues must be attached to at least one exchange in order to receive messages fr
9
11
 
10
12
  =end
11
13
 
12
- class Queue < Qrack::Queue
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
13
19
 
14
- def initialize(client, name, opts = {})
15
- # check connection to server
16
- raise Bunny::ConnectionError, 'Not connected to server' if client.status == :not_connected
17
-
18
- @client = client
19
- @opts = opts
20
+ @client = client
21
+ @opts = opts
20
22
  @delivery_tag = nil
21
23
  @subscription = nil
22
24
 
@@ -30,22 +32,39 @@ Queues must be attached to at least one exchange in order to receive messages fr
30
32
  :auto_delete => true
31
33
  }.merge(opts)
32
34
  end
33
-
34
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
35
- # response that will not be sent by the server
36
- opts.delete(:nowait)
37
-
38
- client.send_frame(
39
- Qrack::Protocol::Queue::Declare.new({ :queue => name || '', :nowait => false }.merge(opts))
40
- )
41
-
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
+
42
44
  method = client.next_method
43
45
 
44
- client.check_response(method, Qrack::Protocol::Queue::DeclareOk, "Error declaring queue #{name}")
46
+ client.check_response(method, Qrack::Protocol::Queue::DeclareOk, "Error declaring queue #{name}")
45
47
 
46
48
  @name = method.queue
47
- client.queues[@name] = self
48
- end
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
49
68
 
50
69
  =begin rdoc
51
70
 
@@ -63,21 +82,21 @@ ask to confirm a single message or a set of messages up to and including a speci
63
82
  is _true_, and the delivery tag is zero, tells the server to acknowledge all outstanding messages.
64
83
 
65
84
  =end
66
-
67
- def ack(opts={})
68
- # Set delivery tag
69
- if delivery_tag.nil? and opts[:delivery_tag].nil?
70
- raise Bunny::AcknowledgementError, "No delivery tag received"
71
- else
72
- self.delivery_tag = opts[:delivery_tag] if delivery_tag.nil?
73
- end
74
-
75
- client.send_frame(
76
- Qrack::Protocol::Basic::Ack.new({:delivery_tag => delivery_tag, :multiple => false}.merge(opts))
77
- )
78
-
79
- # reset delivery tag
80
- self.delivery_tag = nil
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
81
100
  end
82
101
 
83
102
  =begin rdoc
@@ -97,29 +116,30 @@ bound to the direct exchange '' by default. If error occurs, a _Bunny_::_Protoco
97
116
 
98
117
  =end
99
118
 
100
- def bind(exchange, opts = {})
101
- exchange = exchange.respond_to?(:name) ? exchange.name : exchange
102
-
103
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
104
- # response that will not be sent by the server
105
- opts.delete(:nowait)
106
-
107
- client.send_frame(
108
- Qrack::Protocol::Queue::Bind.new({ :queue => name,
109
- :exchange => exchange,
110
- :routing_key => opts.delete(:key),
111
- :nowait => false }.merge(opts))
112
- )
113
-
114
- method = client.next_method
115
-
116
- client.check_response(method, Qrack::Protocol::Queue::BindOk,
117
- "Error binding queue: #{name} to exchange: #{exchange}")
118
-
119
- # return message
120
- :bind_ok
121
- end
122
-
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
+
123
143
  =begin rdoc
124
144
 
125
145
  === DESCRIPTION:
@@ -143,24 +163,24 @@ from queues if successful. If an error occurs raises _Bunny_::_ProtocolError_.
143
163
  <tt>:delete_ok</tt> if successful
144
164
  =end
145
165
 
146
- def delete(opts = {})
147
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
148
- # response that will not be sent by the server
149
- opts.delete(:nowait)
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)
150
172
 
151
- client.send_frame(
152
- Qrack::Protocol::Queue::Delete.new({ :queue => name, :nowait => false }.merge(opts))
153
- )
154
-
155
- method = client.next_method
173
+ client.send_frame(Qrack::Protocol::Queue::Delete.new(opts))
156
174
 
157
- client.check_response(method, Qrack::Protocol::Queue::DeleteOk, "Error deleting queue #{name}")
175
+ method = client.next_method
158
176
 
159
- client.queues.delete(name)
177
+ client.check_response(method, Qrack::Protocol::Queue::DeleteOk, "Error deleting queue #{name}")
160
178
 
161
- # return confirmation
162
- :delete_ok
163
- end
179
+ client.queues.delete(name)
180
+
181
+ # return confirmation
182
+ :delete_ok
183
+ end
164
184
 
165
185
  =begin rdoc
166
186
 
@@ -169,7 +189,7 @@ from queues if successful. If an error occurs raises _Bunny_::_ProtocolError_.
169
189
  Gets a message from a queue in a synchronous way. If error occurs, raises _Bunny_::_ProtocolError_.
170
190
 
171
191
  ==== OPTIONS:
172
-
192
+
173
193
  * <tt>:ack => false (_default_) or true</tt> - If set to _false_, the server does not expect an
174
194
  acknowledgement message from the client. If set to _true_, the server expects an acknowledgement
175
195
  message from the client and will re-queue the message if it does not receive one within a time specified
@@ -191,50 +211,51 @@ will be nil.
191
211
 
192
212
  =end
193
213
 
194
- def pop(opts = {}, &blk)
195
-
196
- # do we want to have to provide an acknowledgement?
197
- ack = opts.delete(:ack)
198
-
199
- client.send_frame(
200
- Qrack::Protocol::Basic::Get.new({ :queue => name,
201
- :consumer_tag => name,
202
- :no_ack => !ack,
203
- :nowait => true }.merge(opts))
204
- )
205
-
206
- method = client.next_method
207
-
208
- if method.is_a?(Qrack::Protocol::Basic::GetEmpty) then
209
- queue_empty = true
210
- elsif !method.is_a?(Qrack::Protocol::Basic::GetOk)
211
- raise Bunny::ProtocolError, "Error getting message from queue #{name}"
212
- end
213
-
214
- if !queue_empty
215
- # get delivery tag to use for acknowledge
216
- self.delivery_tag = method.delivery_tag if ack
217
-
218
- header = client.next_payload
219
-
220
- # If maximum frame size is smaller than message payload body then message
221
- # will have a message header and several message bodies
222
- msg = ''
223
- while msg.length < header.size
224
- msg += client.next_payload
225
- end
226
-
227
- msg_hash = {:header => header, :payload => msg, :delivery_details => method.arguments}
228
-
229
- else
230
- msg_hash = {:header => nil, :payload => :queue_empty, :delivery_details => nil}
231
- end
232
-
233
- # Pass message hash to block or return message hash
234
- blk ? blk.call(msg_hash) : msg_hash
235
-
236
- end
237
-
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
+
238
259
  =begin rdoc
239
260
 
240
261
  === DESCRIPTION:
@@ -251,23 +272,22 @@ without any formal "undo" mechanism. If an error occurs raises _Bunny_::_Protoco
251
272
  <tt>:purge_ok</tt> if successful
252
273
  =end
253
274
 
254
- def purge(opts = {})
255
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
256
- # response that will not be sent by the server
257
- opts.delete(:nowait)
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)
258
279
 
259
- client.send_frame(
260
- Qrack::Protocol::Queue::Purge.new({ :queue => name, :nowait => false }.merge(opts))
261
- )
262
-
263
- method = client.next_method
280
+ opts = { :queue => name, :nowait => false }.merge(opts)
264
281
 
265
- client.check_response(method, Qrack::Protocol::Queue::PurgeOk, "Error purging queue #{name}")
282
+ client.send_frame(Qrack::Protocol::Queue::Purge.new(opts))
283
+
284
+ method = client.next_method
266
285
 
267
- # return confirmation
268
- :purge_ok
286
+ client.check_response(method, Qrack::Protocol::Queue::PurgeOk, "Error purging queue #{name}")
269
287
 
270
- end
288
+ # return confirmation
289
+ :purge_ok
290
+ end
271
291
 
272
292
  =begin rdoc
273
293
 
@@ -276,25 +296,21 @@ without any formal "undo" mechanism. If an error occurs raises _Bunny_::_Protoco
276
296
  Returns hash {:message_count, :consumer_count}.
277
297
 
278
298
  =end
279
-
280
- def status
281
- client.send_frame(
282
- Qrack::Protocol::Queue::Declare.new({ :queue => name, :passive => true })
283
- )
284
- method = client.next_method
285
- {:message_count => method.message_count, :consumer_count => method.consumer_count}
286
- end
287
-
288
-
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
+
289
306
  def subscribe(opts = {}, &blk)
290
- # Create subscription
291
- s = Bunny::Subscription.new(client, self, opts)
292
- s.start(&blk)
293
-
294
- # Reset when subscription finished
295
- @subscription = nil
296
- end
297
-
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
+
298
314
  =begin rdoc
299
315
 
300
316
  === DESCRIPTION:
@@ -312,30 +328,27 @@ the server will not send any more messages for that consumer.
312
328
  <tt>:unsubscribe_ok</tt> if successful
313
329
 
314
330
  =end
315
-
316
- def unsubscribe(opts = {})
317
- # Default consumer_tag from subscription if not passed in
318
- consumer_tag = subscription ? subscription.consumer_tag : opts[:consumer_tag]
319
-
320
- # Must have consumer tag to tell server what to unsubscribe
321
- raise Bunny::UnsubscribeError,
322
- "No consumer tag received" if !consumer_tag
323
-
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
+
324
340
  # Cancel consumer
325
- client.send_frame( Qrack::Protocol::Basic::Cancel.new(:consumer_tag => consumer_tag,
326
- :nowait => false))
327
-
328
- method = client.next_method
329
-
330
- client.check_response(method, Qrack::Protocol::Basic::CancelOk,
331
- "Error unsubscribing from queue #{name}")
332
-
333
- # Reset subscription
334
- @subscription = nil
335
-
336
- # Return confirmation
337
- :unsubscribe_ok
338
-
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
339
352
  end
340
353
 
341
354
  =begin rdoc
@@ -355,35 +368,36 @@ Removes a queue binding from an exchange. If error occurs, a _Bunny_::_ProtocolE
355
368
 
356
369
  =end
357
370
 
358
- def unbind(exchange, opts = {})
359
- exchange = exchange.respond_to?(:name) ? exchange.name : exchange
360
-
361
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
362
- # response that will not be sent by the server
363
- opts.delete(:nowait)
364
-
365
- client.send_frame(
366
- Qrack::Protocol::Queue::Unbind.new({ :queue => name,
367
- :exchange => exchange,
368
- :routing_key => opts.delete(:key),
369
- :nowait => false }.merge(opts)
370
- )
371
- )
372
-
373
- method = client.next_method
374
-
375
- client.check_response(method, Qrack::Protocol::Queue::UnbindOk, "Error unbinding queue #{name}")
376
-
377
- # return message
378
- :unbind_ok
379
- end
380
-
381
- private
382
-
383
- def exchange
384
- @exchange ||= Bunny::Exchange.new(client, '', {:type => :direct, :key => name})
385
- end
386
-
387
- end
388
-
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
+
389
403
  end