hot_bunnies 2.0.0.pre8-java → 2.0.0.pre9-java

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.
data/lib/hot_bunnies.rb CHANGED
@@ -6,10 +6,17 @@ require 'ext/rabbitmq-client'
6
6
 
7
7
  require 'hot_bunnies/version'
8
8
  require 'hot_bunnies/exceptions'
9
+ require 'hot_bunnies/thread_pools'
9
10
  require 'hot_bunnies/session'
10
11
 
12
+ # HotBunnies is a JRuby client for RabbitMQ built on top of the official Java client.
13
+ #
14
+ # @see HotBunnies.connect
15
+ # @see HotBunnies::Session
16
+ # @see HotBunnies::Channel
11
17
  module HotBunnies
12
18
  # Delegates to {HotBunnies::Session.connect}
19
+ # @see HotBunnies::Session.connect
13
20
  def self.connect(*args)
14
21
  Session.connect(*args)
15
22
  end
@@ -2,9 +2,121 @@
2
2
  require "hot_bunnies/shutdown_listener"
3
3
 
4
4
  module HotBunnies
5
+ # ## Channels in RabbitMQ
6
+ #
7
+ # To quote {http://www.rabbitmq.com/resources/specs/amqp0-9-1.pdf AMQP 0.9.1 specification}:
8
+ #
9
+ # AMQP 0.9.1 is a multi-channelled protocol. Channels provide a way to multiplex
10
+ # a heavyweight TCP/IP connection into several light weight connections.
11
+ # This makes the protocol more “firewall friendly” since port usage is predictable.
12
+ # It also means that traffic shaping and other network QoS features can be easily employed.
13
+ # Channels are independent of each other and can perform different functions simultaneously
14
+ # with other channels, the available bandwidth being shared between the concurrent activities.
15
+ #
16
+ #
17
+ # ## Opening Channels
18
+ #
19
+ # Channels can be opened either via `HotBunnies::Session#create_channel` (sufficient in the majority
20
+ # of cases) or by instantiating `HotBunnies::Channel` directly:
21
+ #
22
+ # @example Using {HotBunnies::Session#create_channel}:
23
+ # conn = HotBunnies.new
24
+ # conn.start
25
+ #
26
+ # ch = conn.create_channel
27
+ #
28
+ # This will automatically allocate a channel id.
29
+ #
30
+ # ## Closing Channels
31
+ #
32
+ # Channels are closed via {HotBunnies::Channel#close}. Channels that get a channel-level exception are
33
+ # closed, too. Closed channels can no longer be used. Attempts to use them will raise
34
+ # {HotBunnies::ChannelAlreadyClosed}.
35
+ #
36
+ # @example
37
+ #
38
+ # ch = conn.create_channel
39
+ # ch.close
40
+ #
41
+ # ## Higher-level API
42
+ #
43
+ # HotBunnies offers two sets of methods on {HotBunnies::Channel}: known as higher-level and lower-level
44
+ # APIs, respectively. Higher-level API mimics {http://rubyamqp.info amqp gem} API where
45
+ # exchanges and queues are objects (instance of {HotBunnies::Exchange} and {HotBunnies::Queue}, respectively).
46
+ # Lower-level API is built around AMQP 0.9.1 methods (commands), where queues and exchanges are
47
+ # passed as strings (à la RabbitMQ Java client, {http://clojurerabbitmq.info Langohr} and Pika).
48
+ #
49
+ # ### Queue Operations In Higher-level API
50
+ #
51
+ # * {HotBunnies::Channel#queue} is used to declare queues. The rest of the API is in {HotBunnies::Queue}.
52
+ #
53
+ #
54
+ # ### Exchange Operations In Higher-level API
55
+ #
56
+ # * {HotBunnies::Channel#topic} declares a topic exchange. The rest of the API is in {HotBunnies::Exchange}.
57
+ # * {HotBunnies::Channel#direct} declares a direct exchange.
58
+ # * {HotBunnies::Channel#fanout} declares a fanout exchange.
59
+ # * {HotBunnies::Channel#headers} declares a headers exchange.
60
+ # * {HotBunnies::Channel#default_exchange}
61
+ # * {HotBunnies::Channel#exchange} is used to declare exchanges with type specified as a symbol or string.
62
+ #
63
+ #
64
+ # ## Channel Qos (Prefetch Level)
65
+ #
66
+ # It is possible to control how many messages at most a consumer will be given (before it acknowledges
67
+ # or rejects previously consumed ones). This setting is per channel and controlled via {HotBunnies::Channel#prefetch}.
68
+ #
69
+ #
70
+ # ## Channel IDs
71
+ #
72
+ # Channels are identified by their ids which are integers. HotBunnies takes care of allocating and
73
+ # releasing them as channels are opened and closed. It is almost never necessary to specify
74
+ # channel ids explicitly.
75
+ #
76
+ # There is a limit on the maximum number of channels per connection, usually 65536. Note
77
+ # that allocating channels is very cheap on both client and server so having tens, hundreds
78
+ # or even thousands of channels is possible.
79
+ #
80
+ # ## Channels and Error Handling
81
+ #
82
+ # Channel-level exceptions are more common than connection-level ones and often indicate
83
+ # issues applications can recover from (such as consuming from or trying to delete
84
+ # a queue that does not exist).
85
+ #
86
+ # With HotBunnies, channel-level exceptions are raised as Ruby exceptions, for example,
87
+ # {HotBunnies::NotFound}, that provide access to the underlying `channel.close` method
88
+ # information.
89
+ #
90
+ # @example Handling 404 NOT_FOUND
91
+ # begin
92
+ # ch.queue_delete("queue_that_should_not_exist#{rand}")
93
+ # rescue HotBunnies::NotFound => e
94
+ # puts "Channel-level exception! Code: #{e.channel_close.reply_code}, message: #{e.channel_close.reply_text}"
95
+ # end
96
+ #
97
+ # @example Handling 406 PRECONDITION_FAILED
98
+ # begin
99
+ # ch2 = conn.create_channel
100
+ # q = "hotbunnies.examples.recovery.q#{rand}"
101
+ #
102
+ # ch2.queue_declare(q, :durable => false)
103
+ # ch2.queue_declare(q, :durable => true)
104
+ # rescue HotBunnies::PreconditionFailed => e
105
+ # puts "Channel-level exception! Code: #{e.channel_close.reply_code}, message: #{e.channel_close.reply_text}"
106
+ # ensure
107
+ # conn.create_channel.queue_delete(q)
108
+ # end
109
+ #
110
+ # @see HotBunnies::Session#create_channel
111
+ # @see http://www.rabbitmq.com/tutorials/amqp-concepts.html AMQP 0.9.1 Model Concepts Guide
112
+ # @see http://hotbunnies.info/articles/getting_started.html Getting Started with RabbitMQ Using HotBunnies
113
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers
114
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing
5
115
  class Channel
6
- attr_reader :session, :consumers
116
+ # @return [Array<HotBunnies::Consumer>] Consumers on this channel
117
+ attr_reader :consumers
7
118
 
119
+ # @private
8
120
  def initialize(session, delegate)
9
121
  @connection = session
10
122
  @delegate = delegate
@@ -19,26 +131,41 @@ module HotBunnies
19
131
  end
20
132
  end
21
133
 
134
+ # @return [HotBunnies::Session] Connection this channel is on
22
135
  def client
23
136
  @connection
24
137
  end
25
138
 
139
+ # @return [HotBunnies::Session] Connection this channel is on
140
+ def session
141
+ @connection
142
+ end
143
+
144
+ # @return [HotBunnies::Session] Connection this channel is on
26
145
  def connection
27
146
  @connection
28
147
  end
29
148
 
149
+ # @return [Integer] Channel id
30
150
  def id
31
151
  @delegate.channel_number
32
152
  end
33
153
 
154
+ # @return [Integer] Channel id
34
155
  def number
35
156
  @delegate.channel_number
36
157
  end
37
158
 
159
+ # @return [Integer] Channel id
38
160
  def channel_number
39
161
  @delegate.channel_number
40
162
  end
41
163
 
164
+ # Closes the channel.
165
+ #
166
+ # Closed channels can no longer be used. Closed channel id is
167
+ # returned back to the pool of available ids and may be used by
168
+ # a different channel opened later.
42
169
  def close(code = 200, reason = "Goodbye")
43
170
  v = @delegate.close(code, reason)
44
171
 
@@ -60,40 +187,125 @@ module HotBunnies
60
187
 
61
188
  # @group Exchanges
62
189
 
190
+ # Declares a headers exchange or looks it up in the cache of previously
191
+ # declared exchanges.
192
+ #
193
+ # @param [String] name Exchange name
194
+ # @param [Hash] opts Exchange parameters
195
+ #
196
+ # @option options [String,Symbol] :type (:direct) Exchange type, e.g. :fanout or "x-consistent-hash"
197
+ # @option options [Boolean] :durable (false) Should the exchange be durable?
198
+ # @option options [Boolean] :auto_delete (false) Should the exchange be automatically deleted when no longer in use?
199
+ # @option options [Hash] :arguments ({}) Optional exchange arguments
200
+ #
201
+ # @return [HotBunnies::Exchange] Exchange instance
202
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing guide
203
+ # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
63
204
  def exchange(name, options={})
64
205
  Exchange.new(self, name, options).tap do |x|
65
206
  x.declare!
66
207
  end
67
208
  end
68
209
 
210
+ # Declares a fanout exchange or looks it up in the cache of previously
211
+ # declared exchanges.
212
+ #
213
+ # @param [String] name Exchange name
214
+ # @param [Hash] opts Exchange parameters
215
+ #
216
+ # @option opts [Boolean] :durable (false) Should the exchange be durable?
217
+ # @option opts [Boolean] :auto_delete (false) Should the exchange be automatically deleted when no longer in use?
218
+ # @option opts [Hash] :arguments ({}) Optional exchange arguments (used by RabbitMQ extensions)
219
+ #
220
+ # @return [HotBunnies::Exchange] Exchange instance
221
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing guide
222
+ # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
223
+ # @api public
69
224
  def fanout(name, opts = {})
70
225
  Exchange.new(self, name, opts.merge(:type => "fanout")).tap do |x|
71
226
  x.declare!
72
227
  end
73
228
  end
74
229
 
230
+ # Declares a direct exchange or looks it up in the cache of previously
231
+ # declared exchanges.
232
+ #
233
+ # @param [String] name Exchange name
234
+ # @param [Hash] opts Exchange parameters
235
+ #
236
+ # @option opts [Boolean] :durable (false) Should the exchange be durable?
237
+ # @option opts [Boolean] :auto_delete (false) Should the exchange be automatically deleted when no longer in use?
238
+ # @option opts [Hash] :arguments ({}) Optional exchange arguments (used by RabbitMQ extensions)
239
+ #
240
+ # @return [HotBunnies::Exchange] Exchange instance
241
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing guide
242
+ # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
243
+ # @api public
75
244
  def direct(name, opts = {})
76
245
  Exchange.new(self, name, opts.merge(:type => "direct")).tap do |x|
77
246
  x.declare!
78
247
  end
79
248
  end
80
249
 
250
+ # Declares a topic exchange or looks it up in the cache of previously
251
+ # declared exchanges.
252
+ #
253
+ # @param [String] name Exchange name
254
+ # @param [Hash] opts Exchange parameters
255
+ #
256
+ # @option opts [Boolean] :durable (false) Should the exchange be durable?
257
+ # @option opts [Boolean] :auto_delete (false) Should the exchange be automatically deleted when no longer in use?
258
+ # @option opts [Hash] :arguments ({}) Optional exchange arguments (used by RabbitMQ extensions)
259
+ #
260
+ # @return [HotBunnies::Exchange] Exchange instance
261
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing guide
262
+ # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
263
+ # @api public
81
264
  def topic(name, opts = {})
82
265
  Exchange.new(self, name, opts.merge(:type => "topic")).tap do |x|
83
266
  x.declare!
84
267
  end
85
268
  end
86
269
 
270
+ # Declares a headers exchange or looks it up in the cache of previously
271
+ # declared exchanges.
272
+ #
273
+ # @param [String] name Exchange name
274
+ # @param [Hash] opts Exchange parameters
275
+ #
276
+ # @option opts [Boolean] :durable (false) Should the exchange be durable?
277
+ # @option opts [Boolean] :auto_delete (false) Should the exchange be automatically deleted when no longer in use?
278
+ # @option opts [Hash] :arguments ({}) Optional exchange arguments
279
+ #
280
+ # @return [HotBunnies::Exchange] Exchange instance
281
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing guide
282
+ # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions to AMQP 0.9.1 guide
283
+ # @api public
87
284
  def headers(name, opts = {})
88
285
  Exchange.new(self, name, opts.merge(:type => "headers")).tap do |x|
89
286
  x.declare!
90
287
  end
91
288
  end
92
289
 
290
+ # Provides access to the default exchange
291
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing guide
292
+ # @api public
93
293
  def default_exchange
94
294
  @default_exchange ||= self.exchange("", :durable => true, :auto_delete => false, :type => "direct")
95
295
  end
96
296
 
297
+ # Declares a echange using echange.declare AMQP 0.9.1 method.
298
+ #
299
+ # @param [String] name Exchange name
300
+ # @param [Boolean] durable (false) Should information about this echange be persisted to disk so that it
301
+ # can survive broker restarts? Typically set to true for long-lived exchanges.
302
+ # @param [Boolean] auto_delete (false) Should this echange be deleted when it is no longer used?
303
+ # @param [Boolean] passive (false) If true, exchange will be checked for existence. If it does not
304
+ # exist, {Bunny::NotFound} will be raised.
305
+ #
306
+ # @return RabbitMQ response
307
+ # @see http://hotbunnies.info/articles/echanges.html Exchanges and Publishing guide
308
+ # @api public
97
309
  def exchange_declare(name, type, durable = false, auto_delete = false, arguments = nil)
98
310
  @delegate.exchange_declare(name, type, durable, auto_delete, arguments)
99
311
  end
@@ -103,42 +315,120 @@ module HotBunnies
103
315
 
104
316
  # @group Queues
105
317
 
318
+ # Declares a queue or looks it up in the per-channel cache.
319
+ #
320
+ # @param [String] name Queue name. Pass an empty string to declare a server-named queue (make RabbitMQ generate a unique name).
321
+ # @param [Hash] options Queue properties and other options
322
+ #
323
+ # @option options [Boolean] :durable (false) Should this queue be durable?
324
+ # @option options [Boolean] :auto-delete (false) Should this queue be automatically deleted when the last consumer disconnects?
325
+ # @option options [Boolean] :exclusive (false) Should this queue be exclusive (only can be used by this connection, removed when the connection is closed)?
326
+ # @option options [Boolean] :arguments ({}) Additional optional arguments (typically used by RabbitMQ extensions and plugins)
327
+ #
328
+ # @return [HotBunnies::Queue] Queue that was declared or looked up in the cache
329
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
330
+ # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions guide
331
+ # @api public
106
332
  def queue(name, options={})
107
333
  Queue.new(self, name, options).tap do |q|
108
334
  q.declare!
109
335
  end
110
336
  end
111
337
 
338
+ # Declares a queue using queue.declare AMQP 0.9.1 method.
339
+ #
340
+ # @param [String] name Queue name
341
+ #
342
+ # @param [Boolean] durable (false) Should information about this queue be persisted to disk so that it
343
+ # can survive broker restarts? Typically set to true for long-lived queues.
344
+ # @param [Boolean] auto_delete (false) Should this queue be deleted when the last consumer is cancelled?
345
+ # @param [Boolean] exclusive (false) Should only this connection be able to use this queue?
346
+ # If true, the queue will be automatically deleted when this
347
+ # connection is closed
348
+ # @param [Boolean] passive (false) If true, queue will be checked for existence. If it does not
349
+ # exist, {Bunny::NotFound} will be raised.
350
+ #
351
+ # @return RabbitMQ response
352
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
353
+ # @api public
112
354
  def queue_declare(name, durable, exclusive, auto_delete, arguments = {})
113
355
  converting_rjc_exceptions_to_ruby do
114
356
  @delegate.queue_declare(name, durable, exclusive, auto_delete, arguments)
115
357
  end
116
358
  end
117
359
 
360
+ # Checks if a queue exists using queue.declare AMQP 0.9.1 method.
361
+ # If it does not, a channel exception will be raised.
362
+ #
363
+ # @param [String] name Queue name
364
+ #
365
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
366
+ # @api public
118
367
  def queue_declare_passive(name)
119
368
  converting_rjc_exceptions_to_ruby do
120
369
  @delegate.queue_declare_passive(name)
121
370
  end
122
371
  end
123
372
 
373
+ # Deletes a queue using queue.delete AMQP 0.9.1 method
374
+ #
375
+ # @param [String] name Queue name
376
+ #
377
+ # @param [Boolean] if_empty (false) Should this queue be deleted only if it has no messages?
378
+ # @param [Boolean] if_unused (false) Should this queue be deleted only if it has no consumers?
379
+ #
380
+ # @return RabbitMQ response
381
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
382
+ # @api public
124
383
  def queue_delete(name, if_empty = false, if_unused = false)
125
384
  converting_rjc_exceptions_to_ruby do
126
385
  @delegate.queue_delete(name, if_empty, if_unused)
127
386
  end
128
387
  end
129
388
 
389
+ # Binds a queue to an exchange using queue.bind AMQP 0.9.1 method
390
+ #
391
+ # @param [String] name Queue name
392
+ # @param [String] exchange Exchange name
393
+ #
394
+ # @param [String] routing_key Routing key used for binding
395
+ # @param [Hash] arguments (nil) Optional arguments
396
+ #
397
+ # @return RabbitMQ response
398
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
399
+ # @see http://hotbunnies.info/articles/bindings.html Bindings guide
400
+ # @api public
130
401
  def queue_bind(queue, exchange, routing_key, arguments = nil)
131
402
  converting_rjc_exceptions_to_ruby do
132
403
  @delegate.queue_bind(queue, exchange, routing_key, arguments)
133
404
  end
134
405
  end
135
406
 
407
+ # Unbinds a queue from an exchange using queue.unbind AMQP 0.9.1 method
408
+ #
409
+ # @param [String] name Queue name
410
+ # @param [String] exchange Exchange name
411
+ #
412
+ # @param [String] routing_key Routing key used for binding
413
+ # @param [Hash] arguments ({}) Optional arguments
414
+ #
415
+ # @return RabbitMQ response
416
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
417
+ # @see http://hotbunnies.info/articles/bindings.html Bindings guide
418
+ # @api public
136
419
  def queue_unbind(queue, exchange, routing_key, arguments = nil)
137
420
  converting_rjc_exceptions_to_ruby do
138
421
  @delegate.queue_unbind(queue, exchange, routing_key, arguments)
139
422
  end
140
423
  end
141
424
 
425
+ # Purges a queue (removes all messages from it) using queue.purge AMQP 0.9.1 method.
426
+ #
427
+ # @param [String] name Queue name
428
+ #
429
+ # @return RabbitMQ response
430
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
431
+ # @api public
142
432
  def queue_purge(name)
143
433
  converting_rjc_exceptions_to_ruby do
144
434
  @delegate.queue_purge(name)
@@ -150,6 +440,30 @@ module HotBunnies
150
440
 
151
441
  # @group basic.*
152
442
 
443
+ # Publishes a message using basic.publish AMQP 0.9.1 method.
444
+ #
445
+ # @param [String] exchange Exchange to publish to
446
+ # @param [String] routing_key Routing key
447
+ # @param [String] body Message payload. It will never be modified by Bunny or RabbitMQ in any way.
448
+ # @option opts [Boolean] :mandatory Should the message be returned if it cannot be routed to any queue?
449
+ #
450
+ # @param [Hash] properties Message properties
451
+ #
452
+ # @option properties [Boolean] :persistent Should the message be persisted to disk?
453
+ # @option properties [Integer] :timestamp A timestamp associated with this message
454
+ # @option properties [Integer] :expiration Expiration time after which the message will be deleted
455
+ # @option properties [String] :type Message type, e.g. what type of event or command this message represents. Can be any string
456
+ # @option properties [String] :reply_to Queue name other apps should send the response to
457
+ # @option properties [String] :content_type Message content type (e.g. application/json)
458
+ # @option properties [String] :content_encoding Message content encoding (e.g. gzip)
459
+ # @option properties [String] :correlation_id Message correlated to this one, e.g. what request this message is a reply for
460
+ # @option properties [Integer] :priority Message priority, 0 to 9. Not used by RabbitMQ, only applications
461
+ # @option properties [String] :message_id Any message identifier
462
+ # @option properties [String] :user_id Optional user ID. Verified by RabbitMQ against the actual connection username
463
+ # @option properties [String] :app_id Optional application ID
464
+ #
465
+ # @return [HotBunnies::Channel] Self
466
+ # @api public
153
467
  def basic_publish(exchange, routing_key, mandatory, properties, body)
154
468
  converting_rjc_exceptions_to_ruby do
155
469
  @delegate.basic_publish(exchange, routing_key, mandatory, false, BasicPropertiesBuilder.build_properties_from(properties || Hash.new), body)
@@ -181,10 +495,24 @@ module HotBunnies
181
495
  end
182
496
  end
183
497
 
498
+ # Sets how many messages will be given to consumers on this channel before they
499
+ # have to acknowledge or reject one of the previously consumed messages
500
+ #
501
+ # @param [Integer] prefetch_count Prefetch (QoS setting) for this channel
502
+ # @see http://hotbunnies.info/articles/exchanges.html Exchanges and Publishing guide
503
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
504
+ # @api public
184
505
  def prefetch=(n)
185
506
  basic_qos(n)
186
507
  end
187
508
 
509
+ # Acknowledges a message. Acknowledged messages are completely removed from the queue.
510
+ #
511
+ # @param [Integer] delivery_tag Delivery tag to acknowledge
512
+ # @param [Boolean] multiple (false) Should all unacknowledged messages up to this be acknowledged as well?
513
+ # @see #nack
514
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
515
+ # @api public
188
516
  def ack(delivery_tag, multiple = false)
189
517
  converting_rjc_exceptions_to_ruby do
190
518
  basic_ack(delivery_tag, multiple)
@@ -192,24 +520,120 @@ module HotBunnies
192
520
  end
193
521
  alias acknowledge ack
194
522
 
523
+ # Rejects a message. A rejected message can be requeued or
524
+ # dropped by RabbitMQ.
525
+ #
526
+ # @param [Integer] delivery_tag Delivery tag to reject
527
+ # @param [Boolean] requeue Should this message be requeued instead of dropping it?
528
+ # @see #ack
529
+ # @see #nack
530
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
531
+ # @api public
195
532
  def reject(delivery_tag, requeue = false)
196
533
  converting_rjc_exceptions_to_ruby do
197
534
  basic_reject(delivery_tag, requeue)
198
535
  end
199
536
  end
200
537
 
538
+ # Rejects a message. A rejected message can be requeued or
539
+ # dropped by RabbitMQ. This method is similar to {Bunny::Channel#reject} but
540
+ # supports rejecting multiple messages at once, and is usually preferred.
541
+ #
542
+ # @param [Integer] delivery_tag Delivery tag to reject
543
+ # @param [Boolean] multiple (false) Should all unacknowledged messages up to this be rejected as well?
544
+ # @param [Boolean] requeue (false) Should this message be requeued instead of dropping it?
545
+ # @see #ack
546
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
547
+ # @api public
201
548
  def nack(delivery_tag, multiple = false, requeue = false)
202
549
  converting_rjc_exceptions_to_ruby do
203
550
  basic_nack(delivery_tag, multiple, requeue)
204
551
  end
205
552
  end
206
553
 
554
+ # Rejects or requeues a message.
555
+ #
556
+ # @param [Integer] delivery_tag Delivery tag obtained from delivery info
557
+ # @param [Boolean] requeue Should the message be requeued?
558
+ # @return [NilClass] nil
559
+ #
560
+ # @example Requeue a message
561
+ # conn = Bunny.new
562
+ # conn.start
563
+ #
564
+ # ch = conn.create_channel
565
+ # q.subscribe do |delivery_info, properties, payload|
566
+ # # requeue the message
567
+ # ch.basic_reject(delivery_info.delivery_tag, true)
568
+ # end
569
+ #
570
+ # @example Reject a message
571
+ # conn = Bunny.new
572
+ # conn.start
573
+ #
574
+ # ch = conn.create_channel
575
+ # q.subscribe do |delivery_info, properties, payload|
576
+ # # requeue the message
577
+ # ch.basic_reject(delivery_info.delivery_tag, false)
578
+ # end
579
+ #
580
+ # @example Requeue a message fetched via basic.get
581
+ # conn = Bunny.new
582
+ # conn.start
583
+ #
584
+ # ch = conn.create_channel
585
+ # # we assume the queue exists and has messages
586
+ # delivery_info, properties, payload = ch.basic_get("bunny.examples.queue3", :ack => true)
587
+ # ch.basic_reject(delivery_info.delivery_tag, true)
588
+ #
589
+ # @see #basic_nack
590
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
591
+ # @api public
592
+ def basic_reject(delivery_tag, requeue)
593
+ converting_rjc_exceptions_to_ruby do
594
+ @delegate.basic_reject(delivery_tag, requeue)
595
+ end
596
+ end
597
+
598
+ def basic_ack(delivery_tag, multiple)
599
+ converting_rjc_exceptions_to_ruby do
600
+ @delegate.basic_ack(delivery_tag, multiple)
601
+ end
602
+ end
603
+
604
+ # Rejects or requeues messages just like {Bunny::Channel#basic_reject} but can do so
605
+ # with multiple messages at once.
606
+ #
607
+ # @param [Integer] delivery_tag Delivery tag obtained from delivery info
608
+ # @param [Boolean] requeue Should the message be requeued?
609
+ # @param [Boolean] multiple Should all deliveries up to this one be rejected/requeued?
610
+ # @return [NilClass] nil
611
+ #
612
+ # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
613
+ # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions guide
614
+ # @api public
615
+ def basic_nack(delivery_tag, multiple = false, requeue = false)
616
+ converting_rjc_exceptions_to_ruby do
617
+ @delegate.basic_nack(delivery_tag, multiple, requeue)
618
+ end
619
+ end
620
+
621
+ # Redeliver unacknowledged messages
622
+ #
623
+ # @param [Boolean] requeue Should messages be requeued?
624
+ # @return RabbitMQ response
625
+ # @api public
207
626
  def basic_recover(requeue = true)
208
627
  converting_rjc_exceptions_to_ruby do
209
628
  @delegate.basic_recover(requeue)
210
629
  end
211
630
  end
212
631
 
632
+ # Redeliver unacknowledged messages
633
+ #
634
+ # @param [Boolean] requeue Should messages be requeued?
635
+ # @return RabbitMQ response
636
+ # @api public
213
637
  def basic_recover_async(requeue = true)
214
638
  converting_rjc_exceptions_to_ruby do
215
639
  @delegate.basic_recover_async(requeue)
@@ -1,209 +1,5 @@
1
- module HotBunnies
2
- import com.rabbitmq.client.DefaultConsumer
1
+ require "hot_bunnies/thread_pools"
3
2
 
4
- class BaseConsumer < DefaultConsumer
5
- attr_accessor :consumer_tag
6
-
7
- def initialize(channel)
8
- super(channel)
9
- @channel = channel
10
-
11
- @cancelling = JavaConcurrent::AtomicBoolean.new
12
- @cancelled = JavaConcurrent::AtomicBoolean.new
13
-
14
- @terminated = JavaConcurrent::AtomicBoolean.new
15
- end
16
-
17
- def handleDelivery(consumer_tag, envelope, properties, body)
18
- body = String.from_java_bytes(body)
19
- headers = Headers.new(channel, consumer_tag, envelope, properties)
20
-
21
- deliver(headers, body)
22
- end
23
-
24
- def handleCancel(consumer_tag)
25
- @cancelled.set(true)
26
- @channel.unregister_consumer(consumer_tag)
27
-
28
- if f = @opts[:on_cancellation]
29
- case f.arity
30
- when 0 then
31
- f.call
32
- when 1 then
33
- f.call(self)
34
- when 2 then
35
- f.call(@channel, self)
36
- when 3 then
37
- f.call(@channel, self, consumer_tag)
38
- else
39
- f.call(@channel, self, consumer_tag)
40
- end
41
- end
42
-
43
- @terminated.set(true)
44
- end
45
-
46
- def handleCancelOk(consumer_tag)
47
- @cancelled.set(true)
48
- @channel.unregister_consumer(consumer_tag)
49
-
50
- @terminated.set(true)
51
- end
52
-
53
- def start
54
- end
55
-
56
- def deliver(headers, message)
57
- raise NotImplementedError, 'To be implemented by a subclass'
58
- end
59
-
60
- def cancel
61
- @cancelling.set(true)
62
- response = channel.basic_cancel(consumer_tag)
63
- @cancelled.set(true)
64
- @terminated.set(true)
65
-
66
- response
67
- end
68
-
69
- def cancelled?
70
- @cancelling.get || @cancelled.get
71
- end
72
-
73
- def active?
74
- !terminated?
75
- end
76
-
77
- def terminated?
78
- @terminated.get
79
- end
80
- end
81
-
82
-
83
- class CallbackConsumer < BaseConsumer
84
- def initialize(channel, callback)
85
- raise ArgumentError, "callback must not be nil!" if callback.nil?
86
-
87
- super(channel)
88
- @callback = callback
89
- @callback_arity = @callback.arity
90
- end
91
-
92
- def callback(headers, message)
93
- if @callback_arity == 2
94
- @callback.call(headers, message)
95
- else
96
- @callback.call(message)
97
- end
98
- end
99
- end
100
-
101
- class AsyncCallbackConsumer < CallbackConsumer
102
- def initialize(channel, opts, callback, executor)
103
- super(channel, callback)
104
- @executor = executor
105
- @executor_submit = executor.java_method(:submit, [JavaConcurrent::Runnable.java_class])
106
- @opts = opts
107
- end
108
-
109
- def deliver(headers, message)
110
- unless @executor.shutdown?
111
- @executor_submit.call do
112
- begin
113
- callback(headers, message)
114
- rescue Exception => e
115
- $stderr.puts "Unhandled exception in consumer #{@consumer_tag}: #{e.message}"
116
- end
117
- end
118
- end
119
- end
120
-
121
- def cancel
122
- super
123
-
124
- gracefully_shutdown
125
- end
126
-
127
- def handleCancel(consumer_tag)
128
- super(consumer_tag)
129
-
130
- gracefully_shutdown
131
- end
132
-
133
- def shutdown!
134
- @executor.shutdown_now if @executor
135
- end
136
- alias shut_down! shutdown!
137
-
138
- def gracefully_shut_down
139
- unless @executor.await_termination(1, JavaConcurrent::TimeUnit::SECONDS)
140
- @executor.shutdown_now
141
- end
142
- @terminated.set(true)
143
- end
144
- alias maybe_shut_down_executor gracefully_shut_down
145
- alias gracefully_shutdown gracefully_shut_down
146
- end
147
-
148
- class BlockingCallbackConsumer < CallbackConsumer
149
- include JavaConcurrent
150
-
151
- POISON = :__poison__
152
-
153
- def initialize(channel, buffer_size, opts, callback)
154
- super(channel, callback)
155
- if buffer_size
156
- @internal_queue = ArrayBlockingQueue.new(buffer_size)
157
- else
158
- @internal_queue = LinkedBlockingQueue.new
159
- end
160
-
161
- @opts = opts
162
- end
163
-
164
- def start
165
- interrupted = false
166
- until (@cancelling.get || @cancelled.get) || JavaConcurrent::Thread.current_thread.interrupted?
167
- begin
168
- pair = @internal_queue.take
169
- if pair
170
- if pair == POISON
171
- @cancelling.set(true)
172
- else
173
- callback(*pair)
174
- end
175
- end
176
- rescue InterruptedException => e
177
- interrupted = true
178
- end
179
- end
180
- while (pair = @internal_queue.poll)
181
- callback(*pair)
182
- end
183
- @terminated.set(true)
184
- if interrupted
185
- JavaConcurrent::Thread.current_thread.interrupt
186
- end
187
- end
188
-
189
- def deliver(*pair)
190
- if (@cancelling.get || @cancelled.get) || JavaConcurrent::Thread.current_thread.interrupted?
191
- @internal_queue.offer(pair)
192
- else
193
- begin
194
- @internal_queue.put(pair)
195
- rescue InterruptedException => e
196
- JavaConcurrent::Thread.current_thread.interrupt
197
- end
198
- end
199
- end
200
-
201
- def gracefully_shut_down
202
- @cancelling.set(true)
203
- @internal_queue.offer(POISON)
204
-
205
- @terminated.set(true)
206
- end
207
-
208
- end
209
- end
3
+ require "hot_bunnies/consumers/base"
4
+ require "hot_bunnies/consumers/non_blocking"
5
+ require "hot_bunnies/consumers/blocking"
@@ -0,0 +1,72 @@
1
+ module HotBunnies
2
+ import com.rabbitmq.client.DefaultConsumer
3
+
4
+ class BaseConsumer < DefaultConsumer
5
+ attr_accessor :consumer_tag
6
+
7
+ def initialize(channel)
8
+ super(channel)
9
+ @channel = channel
10
+
11
+ @cancelling = JavaConcurrent::AtomicBoolean.new
12
+ @cancelled = JavaConcurrent::AtomicBoolean.new
13
+
14
+ @terminated = JavaConcurrent::AtomicBoolean.new
15
+ end
16
+
17
+ def handleDelivery(consumer_tag, envelope, properties, body)
18
+ body = String.from_java_bytes(body)
19
+ headers = Headers.new(channel, consumer_tag, envelope, properties)
20
+
21
+ deliver(headers, body)
22
+ end
23
+
24
+ def handleCancel(consumer_tag)
25
+ @cancelled.set(true)
26
+ @channel.unregister_consumer(consumer_tag)
27
+
28
+ if f = @opts[:on_cancellation]
29
+ case f.arity
30
+ when 0 then
31
+ f.call
32
+ when 1 then
33
+ f.call(self)
34
+ when 2 then
35
+ f.call(@channel, self)
36
+ when 3 then
37
+ f.call(@channel, self, consumer_tag)
38
+ else
39
+ f.call(@channel, self, consumer_tag)
40
+ end
41
+ end
42
+
43
+ @terminated.set(true)
44
+ end
45
+
46
+ def handleCancelOk(consumer_tag)
47
+ @cancelled.set(true)
48
+ @channel.unregister_consumer(consumer_tag)
49
+
50
+ @terminated.set(true)
51
+ end
52
+
53
+ def start
54
+ end
55
+
56
+ def deliver(headers, message)
57
+ raise NotImplementedError, 'To be implemented by a subclass'
58
+ end
59
+
60
+ def cancelled?
61
+ @cancelling.get || @cancelled.get
62
+ end
63
+
64
+ def active?
65
+ !terminated?
66
+ end
67
+
68
+ def terminated?
69
+ @terminated.get
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,82 @@
1
+ require "hot_bunnies/consumers/base"
2
+
3
+ module HotBunnies
4
+ class BlockingCallbackConsumer < CallbackConsumer
5
+ include JavaConcurrent
6
+
7
+ POISON = :__poison__
8
+
9
+ def initialize(channel, buffer_size, opts, callback)
10
+ super(channel, callback)
11
+ if buffer_size
12
+ @internal_queue = ArrayBlockingQueue.new(buffer_size)
13
+ else
14
+ @internal_queue = LinkedBlockingQueue.new
15
+ end
16
+
17
+ @opts = opts
18
+ end
19
+
20
+ def cancel
21
+ @cancelling.set(true)
22
+ response = channel.basic_cancel(consumer_tag)
23
+ @cancelled.set(true)
24
+
25
+ @internal_queue.offer(POISON)
26
+ @terminated.set(true)
27
+
28
+ response
29
+ end
30
+
31
+ def start
32
+ interrupted = false
33
+ until (@cancelling.get || @cancelled.get) || JavaConcurrent::Thread.current_thread.interrupted?
34
+ begin
35
+ pair = @internal_queue.take
36
+ if pair
37
+ if pair == POISON
38
+ @cancelling.set(true)
39
+ else
40
+ callback(*pair)
41
+ end
42
+ end
43
+ rescue InterruptedException => e
44
+ interrupted = true
45
+ end
46
+ end
47
+ while (pair = @internal_queue.poll)
48
+ if pair
49
+ if pair == POISON
50
+ @cancelling.set(true)
51
+ else
52
+ callback(*pair)
53
+ end
54
+ end
55
+ end
56
+ @terminated.set(true)
57
+ if interrupted
58
+ JavaConcurrent::Thread.current_thread.interrupt
59
+ end
60
+ end
61
+
62
+ def deliver(*pair)
63
+ if (@cancelling.get || @cancelled.get) || JavaConcurrent::Thread.current_thread.interrupted?
64
+ @internal_queue.offer(pair)
65
+ else
66
+ begin
67
+ @internal_queue.put(pair)
68
+ rescue InterruptedException => e
69
+ JavaConcurrent::Thread.current_thread.interrupt
70
+ end
71
+ end
72
+ end
73
+
74
+ def gracefully_shut_down
75
+ @cancelling.set(true)
76
+ @internal_queue.offer(POISON)
77
+
78
+ @terminated.set(true)
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,73 @@
1
+ require "hot_bunnies/consumers/base"
2
+
3
+ module HotBunnies
4
+ class CallbackConsumer < BaseConsumer
5
+ def initialize(channel, callback)
6
+ raise ArgumentError, "callback must not be nil!" if callback.nil?
7
+
8
+ super(channel)
9
+ @callback = callback
10
+ @callback_arity = @callback.arity
11
+ end
12
+
13
+ def callback(headers, message)
14
+ if @callback_arity == 2
15
+ @callback.call(headers, message)
16
+ else
17
+ @callback.call(message)
18
+ end
19
+ end
20
+ end
21
+
22
+ class AsyncCallbackConsumer < CallbackConsumer
23
+ def initialize(channel, opts, callback, executor)
24
+ super(channel, callback)
25
+ @executor = executor
26
+ @executor_submit = executor.java_method(:submit, [JavaConcurrent::Runnable.java_class])
27
+ @opts = opts
28
+ end
29
+
30
+ def deliver(headers, message)
31
+ unless @executor.shutdown?
32
+ @executor_submit.call do
33
+ begin
34
+ callback(headers, message)
35
+ rescue Exception => e
36
+ $stderr.puts "Unhandled exception in consumer #{@consumer_tag}: #{e.message}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def cancel
43
+ @cancelling.set(true)
44
+ response = channel.basic_cancel(consumer_tag)
45
+ @cancelled.set(true)
46
+ @terminated.set(true)
47
+
48
+ gracefully_shutdown
49
+
50
+ response
51
+ end
52
+
53
+ def handleCancel(consumer_tag)
54
+ super(consumer_tag)
55
+
56
+ gracefully_shutdown
57
+ end
58
+
59
+ def shutdown!
60
+ @executor.shutdown_now if @executor
61
+ end
62
+ alias shut_down! shutdown!
63
+
64
+ def gracefully_shut_down
65
+ unless @executor.await_termination(1, JavaConcurrent::TimeUnit::SECONDS)
66
+ @executor.shutdown_now
67
+ end
68
+ @terminated.set(true)
69
+ end
70
+ alias maybe_shut_down_executor gracefully_shut_down
71
+ alias gracefully_shutdown gracefully_shut_down
72
+ end
73
+ end
@@ -6,6 +6,16 @@ module HotBunnies
6
6
  java_import com.rabbitmq.client.Connection
7
7
  java_import java.util.concurrent.ConcurrentHashMap
8
8
 
9
+ # Connection to a RabbitMQ node.
10
+ #
11
+ # Used to open and close connections and open (create) new channels.
12
+ #
13
+ # @see .connect
14
+ # @see #create_channel
15
+ # @see #close
16
+ # @api public
17
+ # @see http://hotbunnies.info/articles/getting_started.html Getting Started guide
18
+ # @see http://hotbunnies.info/articles/connecting.html Connecting to RabbitMQ guide
9
19
  class Session
10
20
 
11
21
  #
@@ -14,13 +24,26 @@ module HotBunnies
14
24
 
15
25
  # Connects to a RabbitMQ node.
16
26
  #
27
+ # @param [Hash] options Connection options
28
+ #
29
+ # @option options [String] :host ("127.0.0.1") Hostname or IP address to connect to
30
+ # @option options [Integer] :port (5672) Port RabbitMQ listens on
31
+ # @option options [String] :username ("guest") Username
32
+ # @option options [String] :password ("guest") Password
33
+ # @option options [String] :vhost ("/") Virtual host to use
34
+ # @option options [Integer] :heartbeat (600) Heartbeat interval. 0 means no heartbeat.
35
+ # @option options [Boolean] :tls (false) Set to true to use TLS/SSL connection. This will switch port to 5671 by default.
36
+ #
37
+ # @see http://hotbunnies.info/articles/connecting.html Connecting to RabbitMQ guide
38
+ #
39
+ #
17
40
  # @api public
18
41
  def self.connect(options={})
19
42
  cf = ConnectionFactory.new
20
43
 
21
44
  cf.uri = options[:uri] if options[:uri]
22
45
  cf.host = hostname_from(options) if include_host?(options)
23
- cf.port = options[:port] if options[:port]
46
+ cf.port = options[:port].to_i if options[:port]
24
47
  cf.virtual_host = vhost_from(options) if include_vhost?(options)
25
48
  cf.connection_timeout = timeout_from(options) if include_timeout?(options)
26
49
  cf.username = username_from(options) if include_username?(options)
@@ -45,9 +68,13 @@ module HotBunnies
45
68
  new(cf)
46
69
  end
47
70
 
48
- attr_reader :thread, :channels
71
+ # @private
72
+ attr_reader :thread
73
+ # @return [Array<HotBunnies::Channel>] Channels opened on this connection
74
+ attr_reader :channels
49
75
 
50
76
 
77
+ # @private
51
78
  def initialize(connection_factory)
52
79
  @cf = connection_factory
53
80
  @connection = converting_rjc_exceptions_to_ruby do
@@ -58,6 +85,15 @@ module HotBunnies
58
85
  @thread = Thread.current
59
86
  end
60
87
 
88
+ # Opens a new channel.
89
+ #
90
+ # @param [Integer] (nil): Channel number. Pass nil to let HotBunnies allocate an available number
91
+ # in a safe way.
92
+ #
93
+ # @return [HotBunnies::Channel] Newly created channel
94
+ # @see HotBunnies::Channel
95
+ # @see http://hotbunnies.info/articles/getting_started.html Getting Started guide
96
+ # @api public
61
97
  def create_channel(n = nil)
62
98
  jc = if n
63
99
  @connection.create_channel(n)
@@ -86,7 +122,7 @@ module HotBunnies
86
122
  sh
87
123
  end
88
124
 
89
-
125
+ # Flushes the socket used by this connection.
90
126
  def flush
91
127
  @connection.flush
92
128
  end
@@ -95,6 +131,7 @@ module HotBunnies
95
131
  @connection.heartbeat = n
96
132
  end
97
133
 
134
+ # No-op, exists for better API compatibility with Bunny.
98
135
  def start
99
136
  # no-op
100
137
  #
@@ -125,64 +162,79 @@ module HotBunnies
125
162
  @channels[ch.channel_number] = ch
126
163
  end
127
164
 
165
+ # @private
128
166
  def unregister_channel(ch)
129
167
  @channels.delete(ch.channel_number)
130
168
  end
131
169
 
132
170
  protected
133
171
 
172
+ # @private
134
173
  def self.hostname_from(options)
135
174
  options[:host] || options[:hostname] || ConnectionFactory.DEFAULT_HOST
136
175
  end
137
176
 
177
+ # @private
138
178
  def self.include_host?(options)
139
179
  !!(options[:host] || options[:hostname])
140
180
  end
141
181
 
182
+ # @private
142
183
  def self.vhost_from(options)
143
184
  options[:virtual_host] || options[:vhost] || ConnectionFactory.DEFAULT_VHOST
144
185
  end
145
186
 
187
+ # @private
146
188
  def self.include_vhost?(options)
147
189
  !!(options[:virtual_host] || options[:vhost])
148
190
  end
149
191
 
192
+ # @private
150
193
  def self.timeout_from(options)
151
194
  options[:connection_timeout] || options[:timeout]
152
195
  end
153
196
 
197
+ # @private
154
198
  def self.include_timeout?(options)
155
199
  !!(options[:connection_timeout] || options[:timeout])
156
200
  end
157
201
 
202
+ # @private
158
203
  def self.username_from(options)
159
204
  options[:username] || options[:user] || ConnectionFactory.DEFAULT_USER
160
205
  end
161
206
 
207
+ # @private
162
208
  def self.heartbeat_from(options)
163
209
  options[:heartbeat_interval] || options[:requested_heartbeat] || ConnectionFactory.DEFAULT_HEARTBEAT
164
210
  end
165
211
 
212
+ # @private
166
213
  def self.connection_timeout_from(options)
167
214
  options[:connection_timeout_interval] || options[:connection_timeout] || ConnectionFactory.DEFAULT_CONNECTION_TIMEOUT
168
215
  end
169
216
 
217
+ # @private
170
218
  def self.include_username?(options)
171
219
  !!(options[:username] || options[:user])
172
220
  end
173
221
 
222
+ # @private
174
223
  def self.password_from(options)
175
224
  options[:password] || options[:pass] || ConnectionFactory.DEFAULT_PASS
176
225
  end
177
226
 
227
+ # @private
178
228
  def self.include_password?(options)
179
229
  !!(options[:password] || options[:pass])
180
230
  end
181
231
 
232
+ # @private
182
233
  def self.include_heartbeat?(options)
183
234
  !!(options[:heartbeat_interval] || options[:requested_heartbeat] || options[:heartbeat])
184
235
  end
185
236
 
237
+ # @private
186
238
  def self.include_connection_timeout?(options)
187
239
  !!(options[:connection_timeout_interval] || options[:connection_timeout])
188
240
  end
@@ -203,6 +255,7 @@ module HotBunnies
203
255
  end
204
256
  end
205
257
 
258
+ # @private
206
259
  def new_connection
207
260
  converting_rjc_exceptions_to_ruby do
208
261
  @cf.new_connection
@@ -0,0 +1,32 @@
1
+ module HotBunnies
2
+ import java.util.concurrent.Executors
3
+
4
+ # A slighly more Ruby developer-friendly way of instantiating various
5
+ # JDK executors (thread pools).
6
+ class ThreadPools
7
+ # Returns a new thread pool (JDK executor) of a fixed size.
8
+ #
9
+ # @return A thread pool (JDK executor)
10
+ def self.fixed_of_size(n)
11
+ raise ArgumentError.new("n must be a positive integer!") unless Integer === n
12
+ raise ArgumentError.new("n must be a positive integer!") unless n > 0
13
+
14
+ Executors.new_fixed_thread_pool(n)
15
+ end
16
+
17
+ # Returns a new thread pool (JDK executor) of a fixed size of 1.
18
+ #
19
+ # @return A thread pool (JDK executor)
20
+ def self.single_threaded
21
+ Executors.new_single_thread_executor
22
+ end
23
+
24
+ # Returns a new thread pool (JDK executor) that will create new
25
+ # threads as needed.
26
+ #
27
+ # @return A thread pool (JDK executor)
28
+ def self.dynamically_growing
29
+ Executors.new_cached_thread_pool
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module HotBunnies
4
- VERSION = "2.0.0.pre8"
4
+ VERSION = "2.0.0.pre9"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hot_bunnies
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre8
4
+ version: 2.0.0.pre9
5
5
  prerelease: 6
6
6
  platform: java
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-07-04 00:00:00.000000000 Z
13
+ date: 2013-07-11 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: RabbitMQ client for JRuby built around the official RabbitMQ Java client
16
16
  email:
@@ -24,6 +24,9 @@ files:
24
24
  - lib/hot_bunnies.rb
25
25
  - lib/hot_bunnies/channel.rb
26
26
  - lib/hot_bunnies/consumers.rb
27
+ - lib/hot_bunnies/consumers/base.rb
28
+ - lib/hot_bunnies/consumers/blocking.rb
29
+ - lib/hot_bunnies/consumers/non_blocking.rb
27
30
  - lib/hot_bunnies/exceptions.rb
28
31
  - lib/hot_bunnies/exchange.rb
29
32
  - lib/hot_bunnies/juc.rb
@@ -31,6 +34,7 @@ files:
31
34
  - lib/hot_bunnies/queue.rb
32
35
  - lib/hot_bunnies/session.rb
33
36
  - lib/hot_bunnies/shutdown_listener.rb
37
+ - lib/hot_bunnies/thread_pools.rb
34
38
  - lib/hot_bunnies/version.rb
35
39
  homepage: http://hotbunnies.info
36
40
  licenses: []