hot_bunnies 2.0.0.pre10-java → 2.0.0.pre11-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.
@@ -118,17 +118,18 @@ module HotBunnies
118
118
  attr_reader :consumers
119
119
 
120
120
  # @private
121
- def initialize(session, delegate)
121
+ def initialize(session, delegate, thread_pool)
122
122
  @connection = session
123
123
  @delegate = delegate
124
+ @thread_pool = thread_pool
124
125
 
125
- @exchanges = ConcurrentHashMap.new
126
- @queues = ConcurrentHashMap.new
126
+ @exchanges = JavaConcurrent::ConcurrentHashMap.new
127
+ @queues = JavaConcurrent::ConcurrentHashMap.new
127
128
  # we keep track of consumers in part to gracefully shut down their
128
129
  # executors when the channel is closed. This frees library users
129
130
  # from having to worry about this. MK.
130
- @consumers = ConcurrentHashMap.new
131
- @shutdown_hooks = ConcurrentSkipListSet.new
131
+ @consumers = JavaConcurrent::ConcurrentHashMap.new
132
+ @shutdown_hooks = JavaConcurrent::ConcurrentSkipListSet.new
132
133
  @recoveries_counter = JavaConcurrent::AtomicInteger.new(0)
133
134
 
134
135
  on_shutdown do |ch, cause|
@@ -136,35 +137,19 @@ module HotBunnies
136
137
  end
137
138
  end
138
139
 
139
- # @return [HotBunnies::Session] Connection this channel is on
140
- def client
141
- @connection
142
- end
143
-
144
140
  # @return [HotBunnies::Session] Connection this channel is on
145
141
  def session
146
142
  @connection
147
143
  end
148
-
149
- # @return [HotBunnies::Session] Connection this channel is on
150
- def connection
151
- @connection
152
- end
153
-
154
- # @return [Integer] Channel id
155
- def id
156
- @delegate.channel_number
157
- end
158
-
159
- # @return [Integer] Channel id
160
- def number
161
- @delegate.channel_number
162
- end
144
+ alias client session
145
+ alias connection session
163
146
 
164
147
  # @return [Integer] Channel id
165
148
  def channel_number
166
149
  @delegate.channel_number
167
150
  end
151
+ alias id channel_number
152
+ alias number channel_number
168
153
 
169
154
  # Closes the channel.
170
155
  #
@@ -418,7 +403,7 @@ module HotBunnies
418
403
  # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions guide
419
404
  # @api public
420
405
  def queue(name, options={})
421
- dq = Queue.new(self, name, options).tap do |q|
406
+ dq = Queue.new(self, name, @thread_pool, options).tap do |q|
422
407
  q.declare!
423
408
  end
424
409
 
@@ -1,5 +1,4 @@
1
1
  require "hot_bunnies/thread_pools"
2
2
 
3
3
  require "hot_bunnies/consumers/base"
4
- require "hot_bunnies/consumers/non_blocking"
5
4
  require "hot_bunnies/consumers/blocking"
@@ -5,10 +5,11 @@ module HotBunnies
5
5
  attr_accessor :consumer_tag
6
6
  attr_accessor :auto_ack
7
7
 
8
- def initialize(channel, queue)
8
+ def initialize(channel, queue, opts)
9
9
  super(channel)
10
10
  @channel = channel
11
11
  @queue = queue
12
+ @opts = opts
12
13
  @auto_ack = true
13
14
 
14
15
  @cancelling = JavaConcurrent::AtomicBoolean.new
@@ -54,6 +55,11 @@ module HotBunnies
54
55
  end
55
56
 
56
57
  def start
58
+ # no-op
59
+ end
60
+
61
+ def gracefully_shut_down
62
+ # no-op
57
63
  end
58
64
 
59
65
  def deliver(headers, message)
@@ -74,12 +80,33 @@ module HotBunnies
74
80
 
75
81
  # @private
76
82
  def recover_from_network_failure
77
- @consumer_tag = @channel.basic_consume(@queue.name, @auto_ack, self)
78
-
79
83
  @terminated.set(false)
80
84
  @cancelled.set(false)
85
+ @consumer_tag = @channel.basic_consume(@queue.name, @auto_ack, self)
81
86
 
82
87
  @consumer_tag
83
88
  end
84
89
  end
90
+
91
+ class CallbackConsumer < BaseConsumer
92
+ def initialize(channel, queue, opts, callback)
93
+ raise ArgumentError, "callback must not be nil!" if callback.nil?
94
+
95
+ super(channel, queue, opts)
96
+ @callback = callback
97
+ @callback_arity = @callback.arity
98
+ end
99
+
100
+ def deliver(headers, message)
101
+ if @callback_arity == 2
102
+ @callback.call(headers, message)
103
+ else
104
+ @callback.call(message)
105
+ end
106
+ end
107
+
108
+ def cancel
109
+ @channel.basic_cancel(consumer_tag)
110
+ end
111
+ end
85
112
  end
@@ -2,19 +2,15 @@ require "hot_bunnies/consumers/base"
2
2
 
3
3
  module HotBunnies
4
4
  class BlockingCallbackConsumer < CallbackConsumer
5
- include JavaConcurrent
6
-
7
5
  POISON = :__poison__
8
6
 
9
7
  def initialize(channel, queue, buffer_size, opts, callback)
10
- super(channel, queue, callback)
8
+ super(channel, queue, opts, callback)
11
9
  if buffer_size
12
- @internal_queue = ArrayBlockingQueue.new(buffer_size)
10
+ @internal_queue = JavaConcurrent::ArrayBlockingQueue.new(buffer_size)
13
11
  else
14
- @internal_queue = LinkedBlockingQueue.new
12
+ @internal_queue = JavaConcurrent::LinkedBlockingQueue.new
15
13
  end
16
-
17
- @opts = opts
18
14
  end
19
15
 
20
16
  def cancel
@@ -37,10 +33,10 @@ module HotBunnies
37
33
  if pair == POISON
38
34
  @cancelling.set(true)
39
35
  else
40
- callback(*pair)
36
+ @callback.call(*pair)
41
37
  end
42
38
  end
43
- rescue InterruptedException => e
39
+ rescue JavaConcurrent::InterruptedException => e
44
40
  interrupted = true
45
41
  end
46
42
  end
@@ -49,7 +45,7 @@ module HotBunnies
49
45
  if pair == POISON
50
46
  @cancelling.set(true)
51
47
  else
52
- callback(*pair)
48
+ @callback.call(*pair)
53
49
  end
54
50
  end
55
51
  end
@@ -65,7 +61,7 @@ module HotBunnies
65
61
  else
66
62
  begin
67
63
  @internal_queue.put(pair)
68
- rescue InterruptedException => e
64
+ rescue JavaConcurrent::InterruptedException => e
69
65
  JavaConcurrent::Thread.current_thread.interrupt
70
66
  end
71
67
  end
@@ -1,11 +1,9 @@
1
- module JavaConcurrent
2
- java_import 'java.lang.Thread'
3
- java_import 'java.lang.Runnable'
4
- java_import 'java.lang.InterruptedException'
5
- java_import 'java.util.concurrent.Executors'
6
- java_import 'java.util.concurrent.LinkedBlockingQueue'
7
- java_import 'java.util.concurrent.ArrayBlockingQueue'
8
- java_import 'java.util.concurrent.TimeUnit'
9
- java_import 'java.util.concurrent.atomic.AtomicBoolean'
10
- java_import 'java.util.concurrent.atomic.AtomicInteger'
11
- end
1
+ module HotBunnies
2
+ module JavaConcurrent
3
+ java_import 'java.lang.Thread'
4
+ java_import 'java.lang.Runnable'
5
+ java_import 'java.lang.InterruptedException'
6
+ include_package 'java.util.concurrent'
7
+ include_package 'java.util.concurrent.atomic'
8
+ end
9
+ end
@@ -29,9 +29,10 @@ module HotBunnies
29
29
  # @see http://hotbunnies.info/articles/queues.html Queues and Consumers guide
30
30
  # @see http://hotbunnies.info/articles/extensions.html RabbitMQ Extensions guide
31
31
  # @api public
32
- def initialize(channel, name, options={})
32
+ def initialize(channel, name, thread_pool, options={})
33
33
  @channel = channel
34
34
  @name = name
35
+ @thread_pool = thread_pool
35
36
  @options = {:durable => false, :exclusive => false, :auto_delete => false, :passive => false, :arguments => Hash.new}.merge(options)
36
37
 
37
38
  @durable = @options[:durable]
@@ -158,29 +159,16 @@ module HotBunnies
158
159
  end
159
160
  alias pop get
160
161
 
161
- def build_consumer(opts, &block)
162
+ def build_consumer(opts = {}, &block)
162
163
  if opts[:block] || opts[:blocking]
163
164
  BlockingCallbackConsumer.new(@channel, self, opts[:buffer_size], opts, block)
164
165
  else
165
- esf = opts.fetch(:executor_factory, Proc.new {
166
- JavaConcurrent::Executors.new_single_thread_executor
167
- })
168
- es = opts.fetch(:executor, esf.call)
169
- AsyncCallbackConsumer.new(@channel, self, opts.merge(:executor => es, :executor_factory => esf), block)
166
+ CallbackConsumer.new(@channel, self, opts, block)
170
167
  end
171
168
  end
172
169
 
173
170
  def subscribe(opts = {}, &block)
174
- consumer = build_consumer(opts, &block)
175
-
176
- @consumer_tag = @channel.basic_consume(@name, !(opts[:ack] || opts[:manual_ack]), consumer)
177
- consumer.consumer_tag = @consumer_tag
178
-
179
- @default_consumer = consumer
180
- @channel.register_consumer(@consumer_tag, consumer)
181
- consumer.start
182
-
183
- consumer
171
+ subscribe_with(build_consumer(opts, &block))
184
172
  end
185
173
 
186
174
  def subscribe_with(consumer, opts = {})
@@ -189,8 +177,8 @@ module HotBunnies
189
177
 
190
178
  @default_consumer = consumer
191
179
  @channel.register_consumer(@consumer_tag, consumer)
192
- consumer.start
193
180
 
181
+ consumer.start
194
182
  consumer
195
183
  end
196
184
 
@@ -5,8 +5,6 @@ require "set"
5
5
  module HotBunnies
6
6
  java_import com.rabbitmq.client.ConnectionFactory
7
7
  java_import com.rabbitmq.client.Connection
8
- java_import java.util.concurrent.ConcurrentHashMap
9
- java_import java.util.concurrent.ConcurrentSkipListSet
10
8
 
11
9
  # Connection to a RabbitMQ node.
12
10
  #
@@ -73,20 +71,19 @@ module HotBunnies
73
71
  new(cf, options)
74
72
  end
75
73
 
76
- # @private
77
- attr_reader :thread
78
74
  # @return [Array<HotBunnies::Channel>] Channels opened on this connection
79
75
  attr_reader :channels
80
76
 
81
77
 
82
78
  # @private
83
79
  def initialize(connection_factory, opts = {})
84
- @cf = connection_factory
85
- @connection = converting_rjc_exceptions_to_ruby do
80
+ @cf = connection_factory
81
+ @executor_factory = opts[:executor_factory]
82
+ @connection = converting_rjc_exceptions_to_ruby do
86
83
  self.new_connection
87
84
  end
88
- @channels = ConcurrentHashMap.new
89
- @thread = Thread.current
85
+ @channels = JavaConcurrent::ConcurrentHashMap.new
86
+ @thread_pool = ThreadPools.dynamically_growing
90
87
 
91
88
  # should automatic recovery from network failures be used?
92
89
  @automatically_recover = if opts[:automatically_recover].nil? && opts[:automatic_recovery].nil?
@@ -95,7 +92,7 @@ module HotBunnies
95
92
  opts[:automatically_recover] || opts[:automatic_recovery]
96
93
  end
97
94
  @network_recovery_interval = opts.fetch(:network_recovery_interval, DEFAULT_NETWORK_RECOVERY_INTERVAL)
98
- @shutdown_hooks = ConcurrentSkipListSet.new
95
+ @shutdown_hooks = JavaConcurrent::ConcurrentSkipListSet.new
99
96
 
100
97
  if @automatically_recover
101
98
  self.add_automatic_recovery_hook
@@ -118,7 +115,7 @@ module HotBunnies
118
115
  @connection.create_channel
119
116
  end
120
117
 
121
- ch = Channel.new(self, jc)
118
+ ch = Channel.new(self, jc, @thread_pool)
122
119
  register_channel(ch)
123
120
 
124
121
  ch
@@ -129,6 +126,11 @@ module HotBunnies
129
126
  ch.close
130
127
  end
131
128
 
129
+ @thread_pool.shutdown
130
+ unless @thread_pool.await_termination(5, JavaConcurrent::TimeUnit::SECONDS)
131
+ @thread_pool.shutdown_now
132
+ end
133
+
132
134
  @connection.close
133
135
  end
134
136
 
@@ -169,6 +171,7 @@ module HotBunnies
169
171
  @connection = converting_rjc_exceptions_to_ruby do
170
172
  self.new_connection
171
173
  end
174
+ @thread_pool = ThreadPools.dynamically_growing
172
175
  self.recover_shutdown_hooks
173
176
 
174
177
  @channels.each do |id, ch|
@@ -319,7 +322,12 @@ module HotBunnies
319
322
  # @private
320
323
  def new_connection
321
324
  converting_rjc_exceptions_to_ruby do
322
- @cf.new_connection
325
+ if @executor_factory
326
+ ex = @executor_factory.call
327
+ @cf.new_connection(ex)
328
+ else
329
+ @cf.new_connection
330
+ end
323
331
  end
324
332
  end
325
333
  end
@@ -1,6 +1,4 @@
1
1
  module HotBunnies
2
- import java.util.concurrent.Executors
3
-
4
2
  # A slighly more Ruby developer-friendly way of instantiating various
5
3
  # JDK executors (thread pools).
6
4
  class ThreadPools
@@ -11,14 +9,14 @@ module HotBunnies
11
9
  raise ArgumentError.new("n must be a positive integer!") unless Integer === n
12
10
  raise ArgumentError.new("n must be a positive integer!") unless n > 0
13
11
 
14
- Executors.new_fixed_thread_pool(n)
12
+ JavaConcurrent::Executors.new_fixed_thread_pool(n)
15
13
  end
16
14
 
17
15
  # Returns a new thread pool (JDK executor) of a fixed size of 1.
18
16
  #
19
17
  # @return A thread pool (JDK executor)
20
18
  def self.single_threaded
21
- Executors.new_single_thread_executor
19
+ JavaConcurrent::Executors.new_single_thread_executor
22
20
  end
23
21
 
24
22
  # Returns a new thread pool (JDK executor) that will create new
@@ -26,7 +24,7 @@ module HotBunnies
26
24
  #
27
25
  # @return A thread pool (JDK executor)
28
26
  def self.dynamically_growing
29
- Executors.new_cached_thread_pool
27
+ JavaConcurrent::Executors.new_cached_thread_pool
30
28
  end
31
29
  end
32
30
  end
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module HotBunnies
4
- VERSION = "2.0.0.pre10"
4
+ VERSION = "2.0.0.pre11"
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.pre10
4
+ version: 2.0.0.pre11
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-08-11 00:00:00.000000000 Z
13
+ date: 2013-08-20 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:
@@ -26,7 +26,6 @@ files:
26
26
  - lib/hot_bunnies/consumers.rb
27
27
  - lib/hot_bunnies/consumers/base.rb
28
28
  - lib/hot_bunnies/consumers/blocking.rb
29
- - lib/hot_bunnies/consumers/non_blocking.rb
30
29
  - lib/hot_bunnies/exceptions.rb
31
30
  - lib/hot_bunnies/exchange.rb
32
31
  - lib/hot_bunnies/juc.rb
@@ -1,93 +0,0 @@
1
- require "hot_bunnies/consumers/base"
2
-
3
- module HotBunnies
4
- class CallbackConsumer < BaseConsumer
5
- def initialize(channel, queue, callback)
6
- raise ArgumentError, "callback must not be nil!" if callback.nil?
7
-
8
- super(channel, queue)
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, queue, opts, callback)
24
- super(channel, queue, callback)
25
-
26
- # during connection recovery, the executor may be shut down, e.g. due to
27
- # an exception. So we need a way to create a duplicate. Unfortunately, since
28
- # the executor can be passed as an argument, we cannot know how it was
29
- # instantiated. Instead we require a lambda to produce instance of an executor
30
- # as a workaround. MK.
31
- @executor_factory = opts.fetch(:executor_factory, Proc.new {
32
- JavaConcurrent::Executors.new_single_thread_executor
33
- })
34
- @executor = opts.fetch(:executor, @executor_factory.call)
35
- @executor_submit = @executor.java_method(:submit, [JavaConcurrent::Runnable.java_class])
36
- @opts = opts
37
- end
38
-
39
- def deliver(headers, message)
40
- unless @executor.shutdown?
41
- @executor_submit.call do
42
- begin
43
- callback(headers, message)
44
- rescue Exception, java.lang.Throwable => e
45
- # TODO: logging
46
- $stderr.puts "Unhandled exception in consumer #{@consumer_tag}: #{e}"
47
- end
48
- end
49
- end
50
- end
51
-
52
- def cancel
53
- @cancelling.set(true)
54
- response = channel.basic_cancel(consumer_tag)
55
- @cancelled.set(true)
56
- @terminated.set(true)
57
-
58
- gracefully_shutdown
59
-
60
- response
61
- end
62
-
63
- def handleCancel(consumer_tag)
64
- super(consumer_tag)
65
-
66
- gracefully_shutdown
67
- end
68
-
69
- def shutdown!
70
- @executor.shutdown_now if @executor
71
- end
72
- alias shut_down! shutdown!
73
-
74
- def gracefully_shut_down
75
- unless @executor.await_termination(1, JavaConcurrent::TimeUnit::SECONDS)
76
- @executor.shutdown_now
77
- end
78
- @terminated.set(true)
79
- end
80
- alias maybe_shut_down_executor gracefully_shut_down
81
- alias gracefully_shutdown gracefully_shut_down
82
-
83
-
84
- # @private
85
- def recover_from_network_failure
86
- # ensure we have a functioning executor. MK.
87
- @executor = @executor_factory.call
88
- @executor_submit = @executor.java_method(:submit, [JavaConcurrent::Runnable.java_class])
89
-
90
- super
91
- end
92
- end
93
- end