bunny 2.6.1 → 2.6.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d39fdfc39df5c5c84ef856344c2d7242a83b30b7
4
- data.tar.gz: a55c5f91d3bd260d400e79f1e9b58e93c70c9e73
3
+ metadata.gz: a408c8cc518f3c5eda506652d04b7791df76836d
4
+ data.tar.gz: bb55d125ab3558d5c21292f10e9999a5b6d12a6e
5
5
  SHA512:
6
- metadata.gz: 0db597e0e7af75a78d584aca113d250f5fa065da89eef1f988d88fa75ca81c7b2ce211f05a28026024c45e3ce32f86c2f958392f831b87fb5fa076bfd58856bd
7
- data.tar.gz: 03d130d21a488b3d17edb29e08340a0d4429c2324a1c984afa90e667248ff48145efcaac9bcaeaccaa10aabf04211dbdc6c46c6ee7ba92f07bc4fa34fab1ac35
6
+ metadata.gz: fef4df3286150c5baca2823526187fc3cec59a41bf54ac23cbac9a58964070882a17866208d1232f8812742647473729b499429bb1fd6ebe9ffcb4676d34c54b
7
+ data.tar.gz: c7846c6d797c577fb4e34997bf68b4e490893d2e02b12b4e40b5870ab6b028aebdc091be637c4603e8e9d6640bdb14a1cc7056d5cfd5a3335baa33768962c25b
data/.gitignore CHANGED
@@ -21,3 +21,6 @@ debug/*
21
21
  *.dump
22
22
  deploy.docs.sh
23
23
  .ruby-version
24
+ spec/tls/*.pem
25
+ spec/tls/*.pem~
26
+ spec/tls/*.p12
@@ -1,3 +1,9 @@
1
+ ## Changes between Bunny 2.6.1 and 2.6.2 (unreleased)
2
+
3
+ No changes yet.
4
+
5
+
6
+
1
7
  ## Changes between Bunny 2.6.0 and 2.6.1 (October 23rd, 2016)
2
8
 
3
9
  ### Bunny::ConsumerWorkPool#shutdown Terminates Early When It's Safe to Do So
data/Rakefile CHANGED
@@ -10,6 +10,17 @@ RSpec::Core::RakeTask.new(:integration) do |t|
10
10
  t.rspec_opts = "--format progress"
11
11
  end
12
12
 
13
+ RSpec::Core::RakeTask.new(:integration_without_recovery) do |t|
14
+ # same as :integration but excludes client connection recovery tests.
15
+ # useful for sanity checking edge RabbitMQ builds, for instance.
16
+ t.pattern = ["spec/higher_level_api/integration", "spec/lower_level_api/integration", "spec/issues"].
17
+ map { |dir| Dir.glob(File.join(dir, "**", "*_spec.rb")) }.reduce(&:+) -
18
+ ["spec/higher_level_api/integration/tls_connection_spec.rb",
19
+ "spec/higher_level_api/integration/connection_recovery_spec.rb"]
20
+
21
+ t.rspec_opts = "--format progress"
22
+ end
23
+
13
24
  RSpec::Core::RakeTask.new(:unit) do |t|
14
25
  t.pattern = Dir.glob("spec/unit/**/*_spec.rb")
15
26
 
@@ -182,6 +182,9 @@ module Bunny
182
182
  @publishing_mutex = @connection.mutex_impl.new
183
183
  @consumer_mutex = @connection.mutex_impl.new
184
184
 
185
+ @queue_mutex = @connection.mutex_impl.new
186
+ @exchange_mutex = @connection.mutex_impl.new
187
+
185
188
  @unconfirmed_set_mutex = @connection.mutex_impl.new
186
189
 
187
190
  self.reset_continuations
@@ -1516,7 +1519,7 @@ module Bunny
1516
1519
  #
1517
1520
  # @api plugin
1518
1521
  def recover_exchanges
1519
- @exchanges.values.dup.each do |x|
1522
+ @exchange_mutex.synchronize { @exchanges.values }.each do |x|
1520
1523
  x.recover_from_network_failure
1521
1524
  end
1522
1525
  end
@@ -1526,7 +1529,7 @@ module Bunny
1526
1529
  #
1527
1530
  # @api plugin
1528
1531
  def recover_queues
1529
- @queues.values.dup.each do |q|
1532
+ @queue_mutex.synchronize { @queues.values }.each do |q|
1530
1533
  @logger.debug { "Recovering queue #{q.name}" }
1531
1534
  q.recover_from_network_failure
1532
1535
  end
@@ -1541,7 +1544,8 @@ module Bunny
1541
1544
  @work_pool = ConsumerWorkPool.new(@work_pool.size, @work_pool.abort_on_exception)
1542
1545
  @work_pool.start
1543
1546
  end
1544
- @consumers.values.dup.each do |c|
1547
+
1548
+ @consumer_mutex.synchronize { @consumers.values }.each do |c|
1545
1549
  c.recover_from_network_failure
1546
1550
  end
1547
1551
  end
@@ -1861,37 +1865,37 @@ module Bunny
1861
1865
 
1862
1866
  # @private
1863
1867
  def deregister_queue(queue)
1864
- @queues.delete(queue.name)
1868
+ @queue_mutex.synchronize { @queues.delete(queue.name) }
1865
1869
  end
1866
1870
 
1867
1871
  # @private
1868
1872
  def deregister_queue_named(name)
1869
- @queues.delete(name)
1873
+ @queue_mutex.synchronize { @queues.delete(name) }
1870
1874
  end
1871
1875
 
1872
1876
  # @private
1873
1877
  def register_queue(queue)
1874
- @queues[queue.name] = queue
1878
+ @queue_mutex.synchronize { @queues[queue.name] = queue }
1875
1879
  end
1876
1880
 
1877
1881
  # @private
1878
1882
  def find_queue(name)
1879
- @queues[name]
1883
+ @queue_mutex.synchronize { @queues[name] }
1880
1884
  end
1881
1885
 
1882
1886
  # @private
1883
1887
  def deregister_exchange(exchange)
1884
- @exchanges.delete(exchange.name)
1888
+ @exchange_mutex.synchronize { @exchanges.delete(exchange.name) }
1885
1889
  end
1886
1890
 
1887
1891
  # @private
1888
1892
  def register_exchange(exchange)
1889
- @exchanges[exchange.name] = exchange
1893
+ @exchange_mutex.synchronize { @exchanges[exchange.name] = exchange }
1890
1894
  end
1891
1895
 
1892
1896
  # @private
1893
1897
  def find_exchange(name)
1894
- @exchanges[name]
1898
+ @exchange_mutex.synchronize { @exchanges[name] }
1895
1899
  end
1896
1900
 
1897
1901
  protected
@@ -276,7 +276,6 @@ module Bunny
276
276
  # @see http://rubybunny.info/articles/connecting.html
277
277
  # @api public
278
278
  def start
279
-
280
279
  return self if connected?
281
280
 
282
281
  @status_mutex.synchronize { @status = :connecting }
@@ -286,9 +285,7 @@ module Bunny
286
285
  self.reset_continuations
287
286
 
288
287
  begin
289
-
290
288
  begin
291
-
292
289
  # close existing transport if we have one,
293
290
  # to not leak sockets
294
291
  @transport.maybe_initialize_socket
@@ -496,16 +493,18 @@ module Bunny
496
493
 
497
494
  # @private
498
495
  def open_channel(ch)
499
- n = ch.number
500
- self.register_channel(ch)
496
+ @channel_mutex.synchronize do
497
+ n = ch.number
498
+ self.register_channel(ch)
501
499
 
502
- @transport_mutex.synchronize do
503
- @transport.send_frame(AMQ::Protocol::Channel::Open.encode(n, AMQ::Protocol::EMPTY_STRING))
504
- end
505
- @last_channel_open_ok = wait_on_continuations
506
- raise_if_continuation_resulted_in_a_connection_error!
500
+ @transport_mutex.synchronize do
501
+ @transport.send_frame(AMQ::Protocol::Channel::Open.encode(n, AMQ::Protocol::EMPTY_STRING))
502
+ end
503
+ @last_channel_open_ok = wait_on_continuations
504
+ raise_if_continuation_resulted_in_a_connection_error!
507
505
 
508
- @last_channel_open_ok
506
+ @last_channel_open_ok
507
+ end
509
508
  end
510
509
 
511
510
  # @private
@@ -525,8 +524,10 @@ module Bunny
525
524
 
526
525
  # @private
527
526
  def close_all_channels
528
- @channels.reject {|n, ch| n == 0 || !ch.open? }.each do |_, ch|
529
- Bunny::Timeout.timeout(@transport.disconnect_timeout, ClientTimeout) { ch.close }
527
+ @channel_mutex.synchronize do
528
+ @channels.reject {|n, ch| n == 0 || !ch.open? }.each do |_, ch|
529
+ Bunny::Timeout.timeout(@transport.disconnect_timeout, ClientTimeout) { ch.close }
530
+ end
530
531
  end
531
532
  end
532
533
 
@@ -640,8 +641,10 @@ module Bunny
640
641
  @recovering_from_network_failure = true
641
642
  if recoverable_network_failure?(exception)
642
643
  @logger.warn "Recovering from a network failure..."
643
- @channels.each do |n, ch|
644
- ch.maybe_kill_consumer_work_pool!
644
+ @channel_mutex.synchronize do
645
+ @channels.each do |n, ch|
646
+ ch.maybe_kill_consumer_work_pool!
647
+ end
645
648
  end
646
649
  @reader_loop.stop if @reader_loop
647
650
  maybe_shutdown_heartbeat_sender
@@ -701,10 +704,12 @@ module Bunny
701
704
 
702
705
  # @private
703
706
  def recover_channels
704
- @channels.each do |n, ch|
705
- ch.open
707
+ @channel_mutex.synchronize do
708
+ @channels.each do |n, ch|
709
+ ch.open
706
710
 
707
- ch.recover_from_network_failure
711
+ ch.recover_from_network_failure
712
+ end
708
713
  end
709
714
  end
710
715
 
@@ -771,11 +776,11 @@ module Bunny
771
776
  options[:hosts] || ["#{DEFAULT_HOST}:#{port_from(options)}"]
772
777
  addresses = [addresses] unless addresses.is_a? Array
773
778
 
774
- addresses.map! do |address|
779
+ addrs = addresses.map do |address|
775
780
  host_with_port?(address) ? address : "#{address}:#{port_from(@opts)}"
776
781
  end
777
782
 
778
- shuffle_strategy.call addresses
783
+ shuffle_strategy.call(addrs)
779
784
  end
780
785
 
781
786
  # @private
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Bunny
4
4
  # @return [String] Version of the library
5
- VERSION = "2.6.1"
5
+ VERSION = "2.6.2"
6
6
  end
@@ -93,7 +93,7 @@ describe Bunny::Channel, "#basic_consume" do
93
93
 
94
94
  expect(ch.queue(queue_name, :auto_delete => true, :durable => false).message_count).to eq 0
95
95
 
96
- ch.close
96
+ ch.close
97
97
  end
98
98
  end
99
99
  end
@@ -13,7 +13,7 @@ unless ENV["CI"]
13
13
  end
14
14
 
15
15
  let(:concurrency) { 24 }
16
- let(:rate) { 5_000 }
16
+ let(:messages) { 5_000 }
17
17
 
18
18
  it "successfully finish publishing" do
19
19
  body = "сообщение"
@@ -32,10 +32,10 @@ unless ENV["CI"]
32
32
  cht = chs[i]
33
33
  x = cht.default_exchange
34
34
 
35
- rate.times do
35
+ messages.times do
36
36
  x.publish(body)
37
37
  end
38
- puts "Published #{rate} messages..."
38
+ puts "Published #{messages} messages..."
39
39
  cht.wait_for_confirms
40
40
  end
41
41
  t.abort_on_exception = true
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: 2.6.1
4
+ version: 2.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Duncan
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2016-10-22 00:00:00.000000000 Z
15
+ date: 2016-12-17 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: amq-protocol
@@ -196,7 +196,6 @@ files:
196
196
  - spec/stress/concurrent_publishers_stress_spec.rb
197
197
  - spec/stress/connection_open_close_spec.rb
198
198
  - spec/stress/long_running_consumer_spec.rb
199
- - spec/stress/wait_for_confirms_with_connection_loss_stress_spec.rb
200
199
  - spec/tls/ca_certificate.pem
201
200
  - spec/tls/ca_key.pem
202
201
  - spec/tls/client_certificate.pem
@@ -296,7 +295,6 @@ test_files:
296
295
  - spec/stress/concurrent_publishers_stress_spec.rb
297
296
  - spec/stress/connection_open_close_spec.rb
298
297
  - spec/stress/long_running_consumer_spec.rb
299
- - spec/stress/wait_for_confirms_with_connection_loss_stress_spec.rb
300
298
  - spec/tls/ca_certificate.pem
301
299
  - spec/tls/ca_key.pem
302
300
  - spec/tls/client_certificate.pem
@@ -310,4 +308,3 @@ test_files:
310
308
  - spec/unit/concurrent/synchronized_sorted_set_spec.rb
311
309
  - spec/unit/exchange_recovery_spec.rb
312
310
  - spec/unit/version_delivery_tag_spec.rb
313
- has_rdoc: true
@@ -1,131 +0,0 @@
1
- require "spec_helper"
2
-
3
- unless ENV["CI"]
4
- describe "Publisher with wait_for_confirms suffering a lost connection" do
5
- before :all do
6
- @connection = Bunny.new(
7
- :user => "bunny_gem",
8
- :password => "bunny_password",
9
- :vhost => "bunny_testbed",
10
- :recover_from_connection_close => true,
11
- :network_recovery_interval => 0.2,
12
- :recovery_attempts => 3,
13
- :continuation_timeout => 3_000)
14
- @connection.start
15
- end
16
-
17
- after :all do
18
- @connection.close
19
- end
20
-
21
- let(:rate) { 50 }
22
- let(:inner_rate) { 5 }
23
- let(:max_retries) { 3 }
24
- let(:routing_key) { 'confirms' }
25
-
26
- let(:http_client) { RabbitMQ::HTTP::Client.new('http://127.0.0.1:15672') }
27
-
28
- let!(:ch_pub) { @connection.create_channel.tap { |ch| ch.confirm_select } }
29
- let!(:ch_sub) { @connection.create_channel }
30
- let!(:topic) { 'bunny.stress.concurrent.confirms.topic' }
31
- let!(:x) { ch_pub.topic(topic, :durable => true) }
32
- let!(:q) do
33
- ch_sub.queue('', :durable => true).tap do |q|
34
- q.bind(x.name, :routing_key => routing_key)
35
- q.purge
36
- end
37
- end
38
-
39
- def close_all_connections!
40
- http_client.list_connections.each do |conn_info|
41
- begin
42
- http_client.close_connection(conn_info.name)
43
- rescue Bunny::ConnectionForced => e
44
- # This is not a problem, but the specs intermittently believe it is.
45
- printf "Rescued forced connection: #{e.inspect}\n"
46
- end
47
- end
48
- end
49
-
50
- def wait_for_recovery
51
- sleep 1.5
52
- end
53
-
54
- after do
55
- unless ch_sub.closed?
56
- q.delete
57
- ch_sub.close
58
- end
59
- ch_pub.close unless ch_pub.closed?
60
- end
61
-
62
- it "successfully publish and consume all messages" do
63
- begin
64
- subscriber_mutex = Mutex.new
65
- ids_received = Set.new
66
- message_count = nil
67
-
68
- sub = Thread.new do
69
- begin
70
- q.subscribe do |delivery_info, meta, payload|
71
- subscriber_mutex.synchronize do
72
- ids_received << payload.to_i
73
- message_count = q.message_count
74
- end
75
- end
76
- end
77
- end
78
- sub.abort_on_exception = true
79
-
80
- pub = Thread.new do
81
- rate.times do |i|
82
- retries = 0
83
- begin
84
- inner_rate.times do |j|
85
- id = i * inner_rate + j
86
- x.publish(id.to_s, :routing_key => routing_key)
87
- end
88
- until ch_pub.unconfirmed_set.empty?
89
- unless ch_pub.wait_for_confirms
90
- raise "Not all messages acknowledged, nacks: #{ch_pub.nacked_set.inspect}"
91
- end
92
- end
93
- rescue => e
94
- puts "Rescued error in iteration #{i}: #{e.inspect}"
95
- retries += 1
96
- raise if retries > max_retries
97
-
98
- puts "sleeping before retry #{retries}"
99
- sleep 0.5
100
- retry
101
- end
102
- end
103
- puts "Published #{rate * inner_rate} messages..."
104
- end
105
- pub.abort_on_exception = true
106
- sleep 0.2 while ids_received.size < 10
107
-
108
- close_all_connections!
109
- wait_for_recovery
110
-
111
- pub.join
112
-
113
- sleep 0.1 until message_count == 0
114
- puts "Drained queue, winding down..."
115
-
116
- q.delete
117
- ch_pub.close
118
- ch_sub.close
119
- sub.kill
120
-
121
- expect(ch_pub.unconfirmed_set).to be_empty
122
-
123
- expected_ids = Set.new((rate * inner_rate).times)
124
- missing_ids = expected_ids - ids_received
125
- expect(missing_ids).to eq(Set.new)
126
- ensure
127
- sub.kill
128
- end
129
- end
130
- end
131
- end