bunny 2.6.1 → 2.6.2

Sign up to get free protection for your applications and to get access to all the features.
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