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
@@ -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