bunny 0.9.0.pre8 → 0.9.0.pre9

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog.md CHANGED
@@ -1,5 +1,36 @@
1
+ ## Changes between Bunny 0.9.0.pre8 and 0.9.0.pre9
2
+
3
+ ### More Reliable Heartbeat Sender
4
+
5
+ Heartbeat sender no longer slips into an infinite loop if it encounters an exception.
6
+ Instead, it will just stop (and presumably re-started when the network error recovery
7
+ kicks in or the app reconnects manually).
8
+
9
+
10
+ ### Network Recovery After Delay
11
+
12
+ Network reconnection now kicks in after a delay to avoid aggressive
13
+ reconnections in situations when we don't want to endlessly reconnect
14
+ (e.g. when the connection was closed via the Management UI).
15
+
16
+ The `:network_recovery_interval` option passed to `Bunny::Session#initialize` and `Bunny.new`
17
+ controls the interval. Default is 5 seconds.
18
+
19
+
20
+ ### Default Heartbeat Value Is Now Server-Defined
21
+
22
+ Bunny will now use heartbeat value provided by RabbitMQ by default.
23
+
24
+
25
+
1
26
  ## Changes between Bunny 0.9.0.pre7 and 0.9.0.pre8
2
27
 
28
+ ### Stability Improvements
29
+
30
+ Several stability improvements in the network
31
+ layer, connection error handling, and concurrency hazards.
32
+
33
+
3
34
  ### Automatic Connection Recovery Can Be Disabled
4
35
 
5
36
  Automatic connection recovery now can be disabled by passing
data/README.md CHANGED
@@ -36,7 +36,7 @@ gem install bunny --pre
36
36
  To use Bunny 0.9.x in a project managed with Bundler:
37
37
 
38
38
  ``` ruby
39
- gem "bunny", ">= 0.9.0.pre7" # optionally: , :git => "git://github.com/ruby-amqp/bunny.git", :branch => "master"
39
+ gem "bunny", ">= 0.9.0.pre8" # optionally: , :git => "git://github.com/ruby-amqp/bunny.git", :branch => "master"
40
40
  ```
41
41
 
42
42
 
@@ -23,7 +23,7 @@ sleep 0.2
23
23
  delivery_info, _, _ = q.pop(:ack => true)
24
24
  puts "#{dlq.message_count} messages dead lettered so far"
25
25
  puts "Rejecting a message"
26
- ch.nack(delivery_info.delivery_tag, false)
26
+ ch.nack(delivery_info.delivery_tag)
27
27
  sleep 0.2
28
28
  puts "#{dlq.message_count} messages dead lettered so far"
29
29
 
data/lib/bunny/channel.rb CHANGED
@@ -447,13 +447,13 @@ module Bunny
447
447
  # supports rejecting multiple messages at once, and is usually preferred.
448
448
  #
449
449
  # @param [Integer] delivery_tag Delivery tag to reject
450
- # @param [Boolean] requeue Should this message be requeued instead of dropping it?
451
450
  # @param [Boolean] multiple (false) Should all unacknowledged messages up to this be rejected as well?
451
+ # @param [Boolean] requeue (false) Should this message be requeued instead of dropping it?
452
452
  # @see Bunny::Channel#ack
453
453
  # @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
454
454
  # @api public
455
- def nack(delivery_tag, requeue, multiple = false)
456
- basic_nack(delivery_tag, requeue, multiple)
455
+ def nack(delivery_tag, multiple = false, requeue = false)
456
+ basic_nack(delivery_tag, multiple, requeue)
457
457
  end
458
458
 
459
459
  # @endgroup
@@ -713,7 +713,7 @@ module Bunny
713
713
  # ch = conn.create_channel
714
714
  # q.subscribe do |delivery_info, properties, payload|
715
715
  # # requeue the message
716
- # ch.basic_nack(delivery_info.delivery_tag, true)
716
+ # ch.basic_nack(delivery_info.delivery_tag, false, true)
717
717
  # end
718
718
  #
719
719
  # @example Reject a message
@@ -723,7 +723,7 @@ module Bunny
723
723
  # ch = conn.create_channel
724
724
  # q.subscribe do |delivery_info, properties, payload|
725
725
  # # requeue the message
726
- # ch.basic_nack(delivery_info.delivery_tag, false)
726
+ # ch.basic_nack(delivery_info.delivery_tag)
727
727
  # end
728
728
  #
729
729
  # @example Requeue a message fetched via basic.get
@@ -733,7 +733,7 @@ module Bunny
733
733
  # ch = conn.create_channel
734
734
  # # we assume the queue exists and has messages
735
735
  # delivery_info, properties, payload = ch.basic_get("bunny.examples.queue3", :ack => true)
736
- # ch.basic_nack(delivery_info.delivery_tag, true)
736
+ # ch.basic_nack(delivery_info.delivery_tag, false, true)
737
737
  #
738
738
  #
739
739
  # @example Requeue multiple messages fetched via basic.get
@@ -751,12 +751,12 @@ module Bunny
751
751
  # @see http://rubybunny.info/articles/queues.html Queues and Consumers guide
752
752
  # @see http://rubybunny.info/articles/extensions.html RabbitMQ Extensions guide
753
753
  # @api public
754
- def basic_nack(delivery_tag, requeue, multiple = false)
754
+ def basic_nack(delivery_tag, multiple = false, requeue = false)
755
755
  raise_if_no_longer_open!
756
756
  @connection.send_frame(AMQ::Protocol::Basic::Nack.encode(@id,
757
757
  delivery_tag,
758
- requeue,
759
- multiple))
758
+ multiple,
759
+ requeue))
760
760
 
761
761
  nil
762
762
  end
@@ -0,0 +1,28 @@
1
+ require "thread"
2
+
3
+ module Bunny
4
+ module Concurrent
5
+ class ContinuationQueue
6
+ def initialize(*args, &block)
7
+ @q = ::Queue.new(*args)
8
+ end
9
+
10
+ def push(*args)
11
+ @q.push(*args)
12
+ end
13
+ alias << push
14
+
15
+ def pop
16
+ @q.pop
17
+ end
18
+
19
+ def clear
20
+ @q.clear
21
+ end
22
+
23
+ def method_missing(selector, *args, &block)
24
+ @q.__send__(selector, *args, &block)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,56 @@
1
+ if !defined?(JRUBY_VERSION)
2
+ raise "Bunny::Concurrent::LinkedContinuationQueue can only be used on JRuby!"
3
+ end
4
+
5
+ require "java"
6
+
7
+ java_import java.util.concurrent.LinkedBlockingQueue
8
+ java_import java.util.concurrent.TimeUnit
9
+
10
+ module Bunny
11
+ module Concurrent
12
+ # On JRuby, we'd rather use reliable and heavily battle tested j.u.c.
13
+ # primitives with well described semantics than informally specified, clumsy
14
+ # and limited Ruby standard library parts.
15
+ #
16
+ # This is an implementation of the continuation queue on top of the linked blocking
17
+ # queue in j.u.c.
18
+ #
19
+ # Compared to the Ruby standard library Queue, there is one limitation: you cannot
20
+ # push a nil on the queue, it will fail with a null pointer exception.
21
+ class LinkedContinuationQueue
22
+ def initialize(*args, &block)
23
+ @q = LinkedBlockingQueue.new
24
+ end
25
+
26
+ def push(el, timeout_in_ms = nil)
27
+ if timeout_in_ms
28
+ @q.offer(el, timeout_in_ms, TimeUnit.MILLISECONDS)
29
+ else
30
+ @q.offer(el)
31
+ end
32
+ end
33
+ alias << push
34
+
35
+ def pop
36
+ @q.take
37
+ end
38
+
39
+ def poll(timeout_in_ms = nil)
40
+ if timeout_in_ms
41
+ @q.poll(timeout_in_ms, TimeUnit.MILLISECONDS)
42
+ else
43
+ @q.poll
44
+ end
45
+ end
46
+
47
+ def clear
48
+ @q.clear
49
+ end
50
+
51
+ def method_missing(selector, *args, &block)
52
+ @q.__send__(selector, *args, &block)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -157,4 +157,8 @@ module Bunny
157
157
  @other = other
158
158
  end
159
159
  end
160
+
161
+ class ConnectionForced < ConnectionLevelException
162
+ end
163
+
160
164
  end
@@ -46,9 +46,11 @@ module Bunny
46
46
  sleep @interval
47
47
  end
48
48
  rescue IOError => ioe
49
- # ignored
49
+ puts ioe.message
50
+ stop
50
51
  rescue Exception => e
51
52
  puts e.message
53
+ stop
52
54
  end
53
55
  end
54
56
 
data/lib/bunny/session.rb CHANGED
@@ -9,7 +9,11 @@ require "bunny/authentication/credentials_encoder"
9
9
  require "bunny/authentication/plain_mechanism_encoder"
10
10
  require "bunny/authentication/external_mechanism_encoder"
11
11
 
12
- require "bunny/concurrent/condition"
12
+ if defined?(JRUBY_VERSION)
13
+ require "bunny/concurrent/linked_continuation_queue"
14
+ else
15
+ require "bunny/concurrent/continuation_queue"
16
+ end
13
17
 
14
18
  require "amq/protocol/client"
15
19
  require "amq/settings"
@@ -28,7 +32,7 @@ module Bunny
28
32
  # Default password used for connection
29
33
  DEFAULT_PASSWORD = "guest"
30
34
  # Default heartbeat interval, the same value as RabbitMQ 3.0 uses.
31
- DEFAULT_HEARTBEAT = 600
35
+ DEFAULT_HEARTBEAT = :server
32
36
  # @private
33
37
  DEFAULT_FRAME_MAX = 131072
34
38
 
@@ -52,6 +56,8 @@ module Bunny
52
56
 
53
57
  DEFAULT_LOCALE = "en_GB"
54
58
 
59
+ DEFAULT_NETWORK_RECOVERY_INTERVAL = 5.0
60
+
55
61
 
56
62
  #
57
63
  # API
@@ -107,6 +113,7 @@ module Bunny
107
113
  else
108
114
  opts[:automatically_recover] || opts[:automatic_recovery]
109
115
  end
116
+ @network_recovery_interval = opts.fetch(:network_recovery_interval, DEFAULT_NETWORK_RECOVERY_INTERVAL)
110
117
 
111
118
  @status = :not_connected
112
119
 
@@ -124,7 +131,7 @@ module Bunny
124
131
  @network_mutex = Mutex.new
125
132
  @channels = Hash.new
126
133
 
127
- @continuations = ::Queue.new
134
+ self.reset_continuations
128
135
  end
129
136
 
130
137
  # @return [String] RabbitMQ hostname (or IP address) used
@@ -136,6 +143,9 @@ module Bunny
136
143
  # @return [String] Virtual host used
137
144
  def virtual_host; self.vhost; end
138
145
 
146
+ # @return [Integer] Heartbeat interval used
147
+ def heartbeat_interval; self.heartbeat; end
148
+
139
149
  # @return [Boolean] true if this connection uses TLS (SSL)
140
150
  def uses_tls?
141
151
  @transport.uses_tls?
@@ -148,11 +158,18 @@ module Bunny
148
158
  end
149
159
  alias ssl? uses_ssl?
150
160
 
161
+ # @return [Boolean] true if this connection uses a separate thread for I/O activity
162
+ def threaded?
163
+ @threaded
164
+ end
165
+
151
166
  # Starts connection process
152
167
  # @api public
153
168
  def start
154
- @continuations = ::Queue.new
169
+ return self if connected?
170
+
155
171
  @status = :connecting
172
+ self.reset_continuations
156
173
 
157
174
  self.initialize_transport
158
175
 
@@ -163,6 +180,8 @@ module Bunny
163
180
  self.start_main_loop if @threaded
164
181
 
165
182
  @default_channel = self.create_channel
183
+
184
+ self
166
185
  end
167
186
 
168
187
  def read_write_timeout
@@ -197,6 +216,10 @@ module Bunny
197
216
  end
198
217
  alias stop close
199
218
 
219
+ # Creates a temporary channel, yields it to the block given to this
220
+ # method and closes it.
221
+ #
222
+ # @return [Bunny::Session] self
200
223
  def with_channel(n = nil)
201
224
  ch = create_channel(n)
202
225
  yield ch
@@ -205,7 +228,7 @@ module Bunny
205
228
  self
206
229
  end
207
230
 
208
-
231
+ # @return [Boolean] true if this connection is still not fully open
209
232
  def connecting?
210
233
  status == :connecting
211
234
  end
@@ -215,10 +238,11 @@ module Bunny
215
238
  end
216
239
 
217
240
  def open?
218
- (status == :open || status == :connected) && @transport.open?
241
+ (status == :open || status == :connected || status == :connecting) && @transport.open?
219
242
  end
220
243
  alias connected? open?
221
244
 
245
+ # @return [Boolean] true if this connection has automatic recovery from network failure enabled
222
246
  def automatically_recover?
223
247
  @automatically_recover
224
248
  end
@@ -318,6 +342,8 @@ module Bunny
318
342
  when AMQ::Protocol::Connection::Close then
319
343
  @last_connection_error = instantiate_connection_level_exception(method)
320
344
  @continuations.push(method)
345
+
346
+ raise @last_connection_error
321
347
  when AMQ::Protocol::Connection::CloseOk then
322
348
  @last_connection_close_ok = method
323
349
  begin
@@ -332,7 +358,7 @@ module Bunny
332
358
  puts e.message
333
359
  puts e.backtrace
334
360
  ensure
335
- @continuations.push(nil)
361
+ @continuations.push(:__unblock__)
336
362
  end
337
363
  when AMQ::Protocol::Channel::Close then
338
364
  begin
@@ -376,6 +402,8 @@ module Bunny
376
402
  def handle_network_failure(exception)
377
403
  raise NetworkErrorWrapper.new(exception) unless @threaded
378
404
 
405
+ @status = :disconnected
406
+
379
407
  if !recovering_from_network_failure?
380
408
  @recovering_from_network_failure = true
381
409
  if recoverable_network_failure?(exception)
@@ -406,6 +434,7 @@ module Bunny
406
434
  # @private
407
435
  def recover_from_network_failure
408
436
  begin
437
+ sleep @network_recovery_interval
409
438
  # puts "About to start recovery..."
410
439
  start
411
440
 
@@ -416,7 +445,7 @@ module Bunny
416
445
  end
417
446
  rescue TCPConnectionFailed, AMQ::Protocol::EmptyResponseError => e
418
447
  # puts "TCP connection failed, reconnecting in 5 seconds"
419
- sleep 5.0
448
+ sleep @network_recovery_interval
420
449
  retry if recoverable_network_failure?(e)
421
450
  end
422
451
  end
@@ -443,11 +472,13 @@ module Bunny
443
472
  case frame
444
473
  when AMQ::Protocol::Connection::Close then
445
474
  klass = case frame.reply_code
475
+ when 320 then
476
+ ConnectionForced
446
477
  when 503 then
447
478
  InvalidCommand
448
479
  when 504 then
449
480
  ChannelError
450
- when 504 then
481
+ when 505 then
451
482
  UnexpectedFrame
452
483
  else
453
484
  raise "Unknown reply code: #{frame.reply_code}, text: #{frame.reply_text}"
@@ -530,6 +561,11 @@ module Bunny
530
561
  @event_loop ||= MainLoop.new(@transport, self, Thread.current)
531
562
  end
532
563
 
564
+ # @private
565
+ def maybe_shutdown_main_loop
566
+ @event_loop.stop if @event_loop
567
+ end
568
+
533
569
  # @private
534
570
  def signal_activity!
535
571
  @heartbeat_sender.signal_activity! if @heartbeat_sender
@@ -633,7 +669,7 @@ module Bunny
633
669
  @frame_max = negotiate_value(@client_frame_max, connection_tune.frame_max)
634
670
  @channel_max = negotiate_value(@client_channel_max, connection_tune.channel_max)
635
671
  # this allows for disabled heartbeats. MK.
636
- @heartbeat = if 0 == @client_heartbeat || @client_heartbeat.nil?
672
+ @heartbeat = if heartbeat_disabled?(@client_heartbeat)
637
673
  0
638
674
  else
639
675
  negotiate_value(@client_heartbeat, connection_tune.heartbeat)
@@ -665,8 +701,14 @@ module Bunny
665
701
  raise "could not open connection: server did not respond with connection.open-ok" unless connection_open_ok.is_a?(AMQ::Protocol::Connection::OpenOk)
666
702
  end
667
703
 
704
+ def heartbeat_disabled?(val)
705
+ 0 == val || val.nil?
706
+ end
707
+
668
708
  # @api private
669
709
  def negotiate_value(client_value, server_value)
710
+ return server_value if client_value == :server
711
+
670
712
  if client_value == 0 || server_value == 0
671
713
  [client_value, server_value].max
672
714
  else
@@ -708,6 +750,15 @@ module Bunny
708
750
  Authentication::CredentialsEncoder.for_session(self)
709
751
  end
710
752
 
753
+ # @api private
754
+ def reset_continuations
755
+ @continuations = if defined?(JRUBY_VERSION)
756
+ Concurrent::LinkedContinuationQueue.new
757
+ else
758
+ Concurrent::ContinuationQueue.new
759
+ end
760
+ end
761
+
711
762
  # @api private
712
763
  def wait_on_continuations
713
764
  unless @threaded
data/lib/bunny/socket.rb CHANGED
@@ -14,7 +14,7 @@ module Bunny
14
14
  if Socket.constants.include?('TCP_NODELAY') || Socket.constants.include?(:TCP_NODELAY)
15
15
  sock.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, true)
16
16
  end
17
- sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options[:keepalive]
17
+ sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true) if options.fetch(:keepalive, true)
18
18
  sock.options = {:host => host, :port => port}.merge(options)
19
19
  sock
20
20
  end
data/lib/bunny/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Bunny
4
- VERSION = "0.9.0.pre8"
4
+ VERSION = "0.9.0.pre9"
5
5
  end
@@ -51,7 +51,7 @@ describe Bunny::Channel, "#nack" do
51
51
  subject.on_error do |ch, channel_close|
52
52
  @channel_close = channel_close
53
53
  end
54
- subject.nack(82, true)
54
+ subject.nack(82, false, true)
55
55
 
56
56
  sleep 0.5
57
57
 
@@ -14,6 +14,7 @@ describe "Publishing a message to the default exchange" do
14
14
 
15
15
  context "with all default delivery and message properties" do
16
16
  it "routes messages to a queue with the same name as the routing key" do
17
+ connection.should be_threaded
17
18
  ch = connection.create_channel
18
19
 
19
20
  q = ch.queue("", :exclusive => true)
@@ -34,6 +35,7 @@ describe "Publishing a message to the default exchange" do
34
35
 
35
36
  context "with all default delivery and message properties" do
36
37
  it "routes the messages and preserves all the metadata" do
38
+ connection.should be_threaded
37
39
  ch = connection.create_channel
38
40
 
39
41
  q = ch.queue("", :exclusive => true)
@@ -55,4 +57,31 @@ describe "Publishing a message to the default exchange" do
55
57
  ch.close
56
58
  end
57
59
  end
60
+
61
+
62
+ context "with all default delivery and message properties on a single-threaded connection" do
63
+ let(:connection) do
64
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed", :threaded => false)
65
+ c.start
66
+ c
67
+ end
68
+
69
+ it "routes messages to a queue with the same name as the routing key" do
70
+ connection.should_not be_threaded
71
+ ch = connection.create_channel
72
+
73
+ q = ch.queue("", :exclusive => true)
74
+ x = ch.default_exchange
75
+
76
+ x.publish("xyzzy", :routing_key => q.name).
77
+ publish("xyzzy", :routing_key => q.name).
78
+ publish("xyzzy", :routing_key => q.name).
79
+ publish("xyzzy", :routing_key => q.name)
80
+
81
+ sleep(1)
82
+ q.message_count.should == 4
83
+
84
+ ch.close
85
+ end
86
+ end
58
87
  end
@@ -189,7 +189,7 @@ describe Bunny::Session do
189
189
  end
190
190
 
191
191
  it "successfully connects" do
192
- subject.start
192
+ 5.times { subject.start }
193
193
  subject.should be_connected
194
194
 
195
195
  subject.server_properties.should_not be_nil
@@ -24,7 +24,7 @@ describe "A message" do
24
24
 
25
25
  delivery_info, _, _ = q.pop(:ack => true)
26
26
  dlq.message_count.should be_zero
27
- ch.nack(delivery_info.delivery_tag, false)
27
+ ch.nack(delivery_info.delivery_tag)
28
28
 
29
29
  sleep 0.2
30
30
  q.message_count.should be_zero
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ describe "Client-defined heartbeat interval" do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed", :heartbeat_interval => 4)
6
+ c.start
7
+ c
8
+ end
9
+
10
+ it "can be enabled explicitly" do
11
+ sleep 5.0
12
+
13
+ connection.close
14
+ end
15
+ end
16
+
17
+
18
+ describe "Server-defined heartbeat interval" do
19
+ let(:connection) do
20
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed", :heartbeat_interval => :server)
21
+ c.start
22
+ c
23
+ end
24
+
25
+ it "can be enabled explicitly" do
26
+ puts "Sleeping for 5 seconds with heartbeat interval of 4"
27
+ sleep 5.0
28
+
29
+ connection.close
30
+ end
31
+ end
@@ -0,0 +1,49 @@
1
+ require "spec_helper"
2
+
3
+ describe "Rapidly opening and closing lots of channels on a non-threaded connection" do
4
+ let(:connection) do
5
+ c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed", :automatic_recovery => false, :threaded => false)
6
+ c.start
7
+ c
8
+ end
9
+
10
+ after :all do
11
+ connection.close
12
+ end
13
+
14
+ context "in a single-threaded scenario" do
15
+ let(:n) { 500 }
16
+
17
+ it "works correctly" do
18
+ xs = Array.new(n) { connection.create_channel }
19
+ puts "Opened #{n} channels"
20
+
21
+ xs.size.should == n
22
+ xs.each do |ch|
23
+ ch.close
24
+ end
25
+ end
26
+ end
27
+
28
+ context "in a multi-threaded scenario" do
29
+ # actually, on MRI values greater than ~100 will eventually cause write
30
+ # operations to fail with a timeout (1 second is not enough)
31
+ # which will cause recovery to re-acquire @channel_mutex in Session.
32
+ # Because Ruby's mutexes are not re-entrant, it will raise a ThreadError.
33
+ #
34
+ # But this already demonstrates that within these platform constraints,
35
+ # Bunny is safe to use in such scenarios.
36
+ let(:n) { 50 }
37
+
38
+ it "works correctly" do
39
+ n.times do
40
+ t = Thread.new do
41
+ ch = connection.create_channel
42
+
43
+ ch.close
44
+ end
45
+ t.abort_on_exception = true
46
+ end
47
+ end
48
+ end
49
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bunny
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0.pre8
4
+ version: 0.9.0.pre9
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2013-03-12 00:00:00.000000000 Z
16
+ date: 2013-04-22 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: amq-protocol
@@ -93,6 +93,8 @@ files:
93
93
  - lib/bunny/channel_id_allocator.rb
94
94
  - lib/bunny/compatibility.rb
95
95
  - lib/bunny/concurrent/condition.rb
96
+ - lib/bunny/concurrent/continuation_queue.rb
97
+ - lib/bunny/concurrent/linked_continuation_queue.rb
96
98
  - lib/bunny/consumer.rb
97
99
  - lib/bunny/consumer_tag_generator.rb
98
100
  - lib/bunny/consumer_work_pool.rb
@@ -134,6 +136,7 @@ files:
134
136
  - spec/higher_level_api/integration/exchange_declare_spec.rb
135
137
  - spec/higher_level_api/integration/exchange_delete_spec.rb
136
138
  - spec/higher_level_api/integration/exchange_unbind_spec.rb
139
+ - spec/higher_level_api/integration/heartbeat_spec.rb
137
140
  - spec/higher_level_api/integration/message_properties_access_spec.rb
138
141
  - spec/higher_level_api/integration/predeclared_exchanges_spec.rb
139
142
  - spec/higher_level_api/integration/publisher_confirms_spec.rb
@@ -155,6 +158,7 @@ files:
155
158
  - spec/lower_level_api/integration/basic_consume_spec.rb
156
159
  - spec/spec_helper.rb
157
160
  - spec/stress/channel_open_stress_spec.rb
161
+ - spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb
158
162
  - spec/stress/concurrent_consumers_stress_spec.rb
159
163
  - spec/stress/concurrent_publishers_stress_spec.rb
160
164
  - spec/unit/bunny_spec.rb
@@ -211,6 +215,7 @@ test_files:
211
215
  - spec/higher_level_api/integration/exchange_declare_spec.rb
212
216
  - spec/higher_level_api/integration/exchange_delete_spec.rb
213
217
  - spec/higher_level_api/integration/exchange_unbind_spec.rb
218
+ - spec/higher_level_api/integration/heartbeat_spec.rb
214
219
  - spec/higher_level_api/integration/message_properties_access_spec.rb
215
220
  - spec/higher_level_api/integration/predeclared_exchanges_spec.rb
216
221
  - spec/higher_level_api/integration/publisher_confirms_spec.rb
@@ -232,6 +237,7 @@ test_files:
232
237
  - spec/lower_level_api/integration/basic_consume_spec.rb
233
238
  - spec/spec_helper.rb
234
239
  - spec/stress/channel_open_stress_spec.rb
240
+ - spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb
235
241
  - spec/stress/concurrent_consumers_stress_spec.rb
236
242
  - spec/stress/concurrent_publishers_stress_spec.rb
237
243
  - spec/unit/bunny_spec.rb