bunny 0.5.2 → 0.5.3

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.
@@ -88,6 +88,10 @@ if any, is committed.
88
88
  cannot be routed to a queue consumer immediately. If set to _true_, the server will return an
89
89
  undeliverable message with a Return method. If set to _false_, the server will queue the message,
90
90
  but with no guarantee that it will ever be consumed.
91
+ * <tt>:persistent => true or false (_default_)</tt> - Tells the server whether to persist the message
92
+ If set to _true_, the message will be persisted to disk and not lost if the server restarts.
93
+ If set to _false_, the message will not be persisted across server restart. Setting to _true_
94
+ incurs a performance penalty as there is an extra cost associated with disk access.
91
95
 
92
96
  ==== RETURNS:
93
97
 
@@ -96,6 +100,7 @@ nil
96
100
  =end
97
101
 
98
102
  def publish(data, opts = {})
103
+ opts = opts.dup
99
104
  out = []
100
105
 
101
106
  out << Qrack::Protocol::Basic::Publish.new(
@@ -155,4 +160,4 @@ if successful. If an error occurs raises _Bunny_::_ProtocolError_.
155
160
 
156
161
  end
157
162
 
158
- end
163
+ end
@@ -89,6 +89,10 @@ if any, is committed.
89
89
  cannot be routed to a queue consumer immediately. If set to _true_, the server will return an
90
90
  undeliverable message with a Return method. If set to _false_, the server will queue the message,
91
91
  but with no guarantee that it will ever be consumed.
92
+ * <tt>:persistent => true or false (_default_)</tt> - Tells the server whether to persist the message
93
+ If set to _true_, the message will be persisted to disk and not lost if the server restarts.
94
+ If set to _false_, the message will not be persisted across server restart. Setting to _true_
95
+ incurs a performance penalty as there is an extra cost associated with disk access.
92
96
 
93
97
  ==== RETURNS:
94
98
 
@@ -97,6 +101,7 @@ nil
97
101
  =end
98
102
 
99
103
  def publish(data, opts = {})
104
+ opts = opts.dup
100
105
  out = []
101
106
 
102
107
  out << Qrack::Protocol09::Basic::Publish.new(
@@ -156,4 +161,4 @@ if successful. If an error occurs raises _Bunny_::_ProtocolError_.
156
161
 
157
162
  end
158
163
 
159
- end
164
+ end
@@ -9,9 +9,7 @@ Queues must be attached to at least one exchange in order to receive messages fr
9
9
 
10
10
  =end
11
11
 
12
- class Queue
13
- attr_reader :name, :client
14
- attr_accessor :delivery_tag
12
+ class Queue < Qrack::Queue
15
13
 
16
14
  def initialize(client, name, opts = {})
17
15
  # check connection to server
@@ -80,6 +78,87 @@ ask to confirm a single message or a set of messages up to and including a speci
80
78
 
81
79
  === DESCRIPTION:
82
80
 
81
+ Binds a queue to an exchange. Until a queue is bound it will not receive any messages. Queues are
82
+ bound to the direct exchange '' by default. If error occurs, a _Bunny_::_ProtocolError_ is raised.
83
+
84
+ * <tt>:key => 'routing key'* <tt>:key => 'routing_key'</tt> - Specifies the routing key for
85
+ the binding. The routing key is used for routing messages depending on the exchange configuration.
86
+ * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
87
+
88
+ ==== RETURNS:
89
+
90
+ <tt>:bind_ok</tt> if successful.
91
+
92
+ =end
93
+
94
+ def bind(exchange, opts = {})
95
+ exchange = exchange.respond_to?(:name) ? exchange.name : exchange
96
+
97
+ # ignore the :nowait option if passed, otherwise program will hang waiting for a
98
+ # response that will not be sent by the server
99
+ opts.delete(:nowait)
100
+
101
+ client.send_frame(
102
+ Qrack::Protocol::Queue::Bind.new({ :queue => name,
103
+ :exchange => exchange,
104
+ :routing_key => opts.delete(:key),
105
+ :nowait => false }.merge(opts))
106
+ )
107
+
108
+ raise Bunny::ProtocolError,
109
+ "Error binding queue #{name}" unless
110
+ client.next_method.is_a?(Qrack::Protocol::Queue::BindOk)
111
+
112
+ # return message
113
+ :bind_ok
114
+ end
115
+
116
+ =begin rdoc
117
+
118
+ === DESCRIPTION:
119
+
120
+ Requests that a queue is deleted from broker/server. When a queue is deleted any pending messages
121
+ are sent to a dead-letter queue if this is defined in the server configuration. Removes reference
122
+ from queues if successful. If an error occurs raises _Bunny_::_ProtocolError_.
123
+
124
+ ==== Options:
125
+
126
+ * <tt>:if_unused => true or false (_default_)</tt> - If set to _true_, the server will only
127
+ delete the queue if it has no consumers. If the queue has consumers the server does not
128
+ delete it but raises a channel exception instead.
129
+ * <tt>:if_empty => true or false (_default_)</tt> - If set to _true_, the server will only
130
+ delete the queue if it has no messages. If the queue is not empty the server raises a channel
131
+ exception.
132
+ * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
133
+
134
+ ==== Returns:
135
+
136
+ <tt>:delete_ok</tt> if successful
137
+ =end
138
+
139
+ def delete(opts = {})
140
+ # ignore the :nowait option if passed, otherwise program will hang waiting for a
141
+ # response that will not be sent by the server
142
+ opts.delete(:nowait)
143
+
144
+ client.send_frame(
145
+ Qrack::Protocol::Queue::Delete.new({ :queue => name, :nowait => false }.merge(opts))
146
+ )
147
+
148
+ raise Bunny::ProtocolError,
149
+ "Error deleting queue #{name}" unless
150
+ client.next_method.is_a?(Qrack::Protocol::Queue::DeleteOk)
151
+
152
+ client.queues.delete(name)
153
+
154
+ # return confirmation
155
+ :delete_ok
156
+ end
157
+
158
+ =begin rdoc
159
+
160
+ === DESCRIPTION:
161
+
83
162
  Gets a message from a queue in a synchronous way. If error occurs, raises _Bunny_::_ProtocolError_.
84
163
 
85
164
  ==== OPTIONS:
@@ -126,54 +205,49 @@ a hash <tt>{:delivery_tag, :redelivered, :exchange, :routing_key, :message_count
126
205
  self.delivery_tag = method.delivery_tag if ack
127
206
 
128
207
  header = client.next_payload
129
- msg = client.next_payload
130
- raise Bunny::MessageError, 'unexpected length' if msg.length < header.size
208
+
209
+ # If maximum frame size is smaller than message payload body then message
210
+ # will have a message header and several message bodies
211
+ msg = ''
212
+ while msg.length < header.size
213
+ msg += client.next_payload
214
+ end
131
215
 
132
216
  # Return message with additional info if requested
133
217
  hdr ? {:header => header, :payload => msg, :delivery_details => method.arguments} : msg
134
218
 
135
219
  end
136
-
220
+
137
221
  =begin rdoc
138
222
 
139
223
  === DESCRIPTION:
140
224
 
141
- Publishes a message to the queue via the default nameless '' direct exchange.
142
-
143
- ==== RETURNS:
144
-
145
- nil
146
-
147
- =end
148
-
149
- def publish(data, opts = {})
150
- exchange.publish(data, opts)
151
- end
225
+ Removes all messages from a queue. It does not cancel consumers. Purged messages are deleted
226
+ without any formal "undo" mechanism. If an error occurs raises _Bunny_::_ProtocolError_.
152
227
 
153
- =begin rdoc
228
+ ==== Options:
154
229
 
155
- === DESCRIPTION:
230
+ * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
156
231
 
157
- Returns message count from Queue#status.
232
+ ==== Returns:
158
233
 
234
+ <tt>:purge_ok</tt> if successful
159
235
  =end
160
236
 
161
- def message_count
162
- s = status
163
- s[:message_count]
164
- end
237
+ def purge(opts = {})
238
+ # ignore the :nowait option if passed, otherwise program will hang waiting for a
239
+ # response that will not be sent by the server
240
+ opts.delete(:nowait)
165
241
 
166
- =begin rdoc
242
+ client.send_frame(
243
+ Qrack::Protocol::Queue::Purge.new({ :queue => name, :nowait => false }.merge(opts))
244
+ )
167
245
 
168
- === DESCRIPTION:
246
+ raise Bunny::ProtocolError, "Error purging queue #{name}" unless client.next_method.is_a?(Qrack::Protocol::Queue::PurgeOk)
169
247
 
170
- Returns consumer count from Queue#status.
248
+ # return confirmation
249
+ :purge_ok
171
250
 
172
- =end
173
-
174
- def consumer_count
175
- s = status
176
- s[:consumer_count]
177
251
  end
178
252
 
179
253
  =begin rdoc
@@ -214,21 +288,27 @@ processing. If error occurs, _Bunny_::_ProtocolError_ is raised.
214
288
  * <tt>:exclusive => true or false (_default_)</tt> - Request exclusive consumer access, meaning
215
289
  only this consumer can access the queue.
216
290
  * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
217
- * <tt>:timeout => number of seconds (default = 0 no timeout) - The subscribe loop will continue to wait for
291
+ * <tt>:timeout => number of seconds - The subscribe loop will continue to wait for
218
292
  messages until terminated (Ctrl-C or kill command) or this timeout interval is reached.
293
+ * <tt>:message_max => max number messages to process</tt> - When the required number of messages
294
+ is processed subscribe loop is exited.
219
295
 
220
296
  ==== RETURNS:
221
297
 
222
298
  If <tt>:header => true</tt> returns hash <tt>{:header, :delivery_details, :payload}</tt> for each message.
223
299
  <tt>:delivery_details</tt> is a hash <tt>{:consumer_tag, :delivery_tag, :redelivered, :exchange, :routing_key}</tt>.
224
300
  If <tt>:header => false</tt> only message payload is returned.
225
- If <tt>:timeout => > 0</tt> is reached returns :timed_out
301
+ If <tt>:timeout => > 0</tt> is reached Qrack::ClientTimeout is raised
226
302
 
227
303
  =end
228
304
 
229
305
  def subscribe(opts = {}, &blk)
230
- consumer_tag = opts[:consumer_tag] || name
231
- secs = opts[:timeout] || 0
306
+ # Get maximum amount of messages to process
307
+ message_max = opts[:message_max] || nil
308
+ return if message_max == 0
309
+
310
+ # If a consumer tag is not passed in the server will generate one
311
+ consumer_tag = opts[:consumer_tag] || nil
232
312
 
233
313
  # ignore the :nowait option if passed, otherwise program will hang waiting for a
234
314
  # response from the server causing an error.
@@ -251,26 +331,32 @@ If <tt>:timeout => > 0</tt> is reached returns :timed_out
251
331
  "Error subscribing to queue #{name}" unless
252
332
  client.next_method.is_a?(Qrack::Protocol::Basic::ConsumeOk)
253
333
 
334
+ # Initialize message counter
335
+ counter = 0
336
+
254
337
  loop do
255
- begin
256
- Timeout::timeout(secs) do
257
- @method = client.next_method
258
- end
259
- rescue Timeout::Error
260
- return :timed_out
261
- end
262
-
263
- break if @method.is_a?(Qrack::Protocol::Basic::CancelOk)
338
+ method = client.next_method(:timeout => opts[:timeout])
264
339
 
265
340
  # get delivery tag to use for acknowledge
266
- self.delivery_tag = @method.delivery_tag if ack
341
+ self.delivery_tag = method.delivery_tag if ack
267
342
 
268
343
  header = client.next_payload
269
- msg = client.next_payload
270
- raise Bunny::MessageError, 'unexpected length' if msg.length < header.size
344
+
345
+ # If maximum frame size is smaller than message payload body then message
346
+ # will have a message header and several message bodies
347
+ msg = ''
348
+ while msg.length < header.size
349
+ msg += client.next_payload
350
+ end
271
351
 
272
352
  # pass the message and related info, if requested, to the block for processing
273
353
  blk.call(hdr ? {:header => header, :payload => msg, :delivery_details => method.arguments} : msg)
354
+
355
+ # Increment message counter
356
+ counter += 1
357
+
358
+ # Exit loop if message_max condition met
359
+ break if !message_max.nil? and counter == message_max
274
360
  end
275
361
 
276
362
  end
@@ -287,6 +373,10 @@ the server will not send any more messages for that consumer.
287
373
  * <tt>:consumer_tag => '_tag_'</tt> - Specifies the identifier for the consumer.
288
374
  * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
289
375
 
376
+ ==== Returns:
377
+
378
+ <tt>:unsubscribe_ok</tt> if successful
379
+
290
380
  =end
291
381
 
292
382
  def unsubscribe(opts = {})
@@ -301,48 +391,10 @@ the server will not send any more messages for that consumer.
301
391
  raise Bunny::ProtocolError,
302
392
  "Error unsubscribing from queue #{name}" unless
303
393
  client.next_method.is_a?(Qrack::Protocol::Basic::CancelOk)
304
-
305
- end
306
-
307
- =begin rdoc
308
-
309
- === DESCRIPTION:
310
-
311
- Binds a queue to an exchange. Until a queue is bound it will not receive any messages. Queues are
312
- bound to the direct exchange '' by default. If error occurs, a _Bunny_::_ProtocolError_ is raised.
313
-
314
- * <tt>:key => 'routing key'* <tt>:key => 'routing_key'</tt> - Specifies the routing key for
315
- the binding. The routing key is used for routing messages depending on the exchange configuration.
316
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
317
-
318
- ==== RETURNS:
319
-
320
- <tt>:bind_ok</tt> if successful.
321
-
322
- =end
323
-
324
- def bind(exchange, opts = {})
325
- exchange = exchange.respond_to?(:name) ? exchange.name : exchange
326
-
327
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
328
- # response that will not be sent by the server
329
- opts.delete(:nowait)
330
-
331
- bindings[exchange] = opts
332
- client.send_frame(
333
- Qrack::Protocol::Queue::Bind.new({ :queue => name,
334
- :exchange => exchange,
335
- :routing_key => opts.delete(:key),
336
- :nowait => false }.merge(opts))
337
- )
338
-
339
- raise Bunny::ProtocolError,
340
- "Error binding queue #{name}" unless
341
- client.next_method.is_a?(Qrack::Protocol::Queue::BindOk)
342
394
 
343
- # return message
344
- :bind_ok
345
- end
395
+ # return confirmation
396
+ :unsubscribe_ok
397
+ end
346
398
 
347
399
  =begin rdoc
348
400
 
@@ -367,8 +419,6 @@ Removes a queue binding from an exchange. If error occurs, a _Bunny_::_ProtocolE
367
419
  # ignore the :nowait option if passed, otherwise program will hang waiting for a
368
420
  # response that will not be sent by the server
369
421
  opts.delete(:nowait)
370
-
371
- bindings.delete(exchange)
372
422
 
373
423
  client.send_frame(
374
424
  Qrack::Protocol::Queue::Unbind.new({ :queue => name,
@@ -386,88 +436,12 @@ Removes a queue binding from an exchange. If error occurs, a _Bunny_::_ProtocolE
386
436
  :unbind_ok
387
437
  end
388
438
 
389
- =begin rdoc
390
-
391
- === DESCRIPTION:
392
-
393
- Requests that a queue is deleted from broker/server. When a queue is deleted any pending messages
394
- are sent to a dead-letter queue if this is defined in the server configuration. Removes reference
395
- from queues if successful. If an error occurs raises _Bunny_::_ProtocolError_.
396
-
397
- ==== Options:
398
-
399
- * <tt>:if_unused => true or false (_default_)</tt> - If set to _true_, the server will only
400
- delete the queue if it has no consumers. If the queue has consumers the server does not
401
- delete it but raises a channel exception instead.
402
- * <tt>:if_empty => true or false (_default_)</tt> - If set to _true_, the server will only
403
- delete the queue if it has no messages. If the queue is not empty the server raises a channel
404
- exception.
405
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
406
-
407
- ==== Returns:
408
-
409
- <tt>:delete_ok</tt> if successful
410
- =end
411
-
412
- def delete(opts = {})
413
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
414
- # response that will not be sent by the server
415
- opts.delete(:nowait)
416
-
417
- client.send_frame(
418
- Qrack::Protocol::Queue::Delete.new({ :queue => name, :nowait => false }.merge(opts))
419
- )
420
-
421
- raise Bunny::ProtocolError,
422
- "Error deleting queue #{name}" unless
423
- client.next_method.is_a?(Qrack::Protocol::Queue::DeleteOk)
424
-
425
- client.queues.delete(name)
426
-
427
- # return confirmation
428
- :delete_ok
429
- end
430
-
431
- =begin rdoc
432
-
433
- === DESCRIPTION:
434
-
435
- Removes all messages from a queue. It does not cancel consumers. Purged messages are deleted
436
- without any formal "undo" mechanism. If an error occurs raises _Bunny_::_ProtocolError_.
437
-
438
- ==== Options:
439
-
440
- * <tt>:nowait => true or false (_default_)</tt> - Ignored by Bunny, always _false_.
441
-
442
- ==== Returns:
443
-
444
- <tt>:purge_ok</tt> if successful
445
- =end
446
-
447
- def purge(opts = {})
448
- # ignore the :nowait option if passed, otherwise program will hang waiting for a
449
- # response that will not be sent by the server
450
- opts.delete(:nowait)
439
+ private
451
440
 
452
- client.send_frame(
453
- Qrack::Protocol::Queue::Purge.new({ :queue => name, :nowait => false }.merge(opts))
454
- )
455
-
456
- raise Bunny::ProtocolError, "Error purging queue #{name}" unless client.next_method.is_a?(Qrack::Protocol::Queue::PurgeOk)
457
-
458
- # return confirmation
459
- :purge_ok
460
-
461
- end
462
-
463
- private
464
- def exchange
441
+ def exchange
465
442
  @exchange ||= Bunny::Exchange.new(client, '', {:type => :direct, :key => name})
466
443
  end
467
-
468
- def bindings
469
- @bindings ||= {}
470
- end
444
+
471
445
  end
472
446
 
473
447
  end