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.
- data/lib/hot_bunnies/channel.rb +11 -26
- data/lib/hot_bunnies/consumers.rb +0 -1
- data/lib/hot_bunnies/consumers/base.rb +30 -3
- data/lib/hot_bunnies/consumers/blocking.rb +7 -11
- data/lib/hot_bunnies/juc.rb +9 -11
- data/lib/hot_bunnies/queue.rb +6 -18
- data/lib/hot_bunnies/session.rb +19 -11
- data/lib/hot_bunnies/thread_pools.rb +3 -5
- data/lib/hot_bunnies/version.rb +1 -1
- metadata +2 -3
- data/lib/hot_bunnies/consumers/non_blocking.rb +0 -93
data/lib/hot_bunnies/channel.rb
CHANGED
@@ -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
|
-
|
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
|
|
@@ -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
|
data/lib/hot_bunnies/juc.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
data/lib/hot_bunnies/queue.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
|
data/lib/hot_bunnies/session.rb
CHANGED
@@ -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
|
85
|
-
@
|
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
|
89
|
-
@
|
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
|
-
@
|
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
|
data/lib/hot_bunnies/version.rb
CHANGED
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.
|
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-
|
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
|