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 +4 -4
- data/.gitignore +3 -0
- data/ChangeLog.md +6 -0
- data/Rakefile +11 -0
- data/lib/bunny/channel.rb +14 -10
- data/lib/bunny/session.rb +25 -20
- data/lib/bunny/version.rb +1 -1
- data/spec/lower_level_api/integration/basic_consume_spec.rb +1 -1
- data/spec/stress/concurrent_publishers_stress_spec.rb +3 -3
- metadata +2 -5
- data/spec/stress/wait_for_confirms_with_connection_loss_stress_spec.rb +0 -131
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a408c8cc518f3c5eda506652d04b7791df76836d
|
4
|
+
data.tar.gz: bb55d125ab3558d5c21292f10e9999a5b6d12a6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fef4df3286150c5baca2823526187fc3cec59a41bf54ac23cbac9a58964070882a17866208d1232f8812742647473729b499429bb1fd6ebe9ffcb4676d34c54b
|
7
|
+
data.tar.gz: c7846c6d797c577fb4e34997bf68b4e490893d2e02b12b4e40b5870ab6b028aebdc091be637c4603e8e9d6640bdb14a1cc7056d5cfd5a3335baa33768962c25b
|
data/.gitignore
CHANGED
data/ChangeLog.md
CHANGED
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
|
|
data/lib/bunny/channel.rb
CHANGED
@@ -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.
|
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.
|
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
|
-
|
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
|
data/lib/bunny/session.rb
CHANGED
@@ -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
|
-
|
500
|
-
|
496
|
+
@channel_mutex.synchronize do
|
497
|
+
n = ch.number
|
498
|
+
self.register_channel(ch)
|
501
499
|
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
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
|
-
|
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
|
-
@
|
529
|
-
|
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
|
-
@
|
644
|
-
ch
|
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
|
-
@
|
705
|
-
ch
|
707
|
+
@channel_mutex.synchronize do
|
708
|
+
@channels.each do |n, ch|
|
709
|
+
ch.open
|
706
710
|
|
707
|
-
|
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
|
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
|
783
|
+
shuffle_strategy.call(addrs)
|
779
784
|
end
|
780
785
|
|
781
786
|
# @private
|
data/lib/bunny/version.rb
CHANGED
@@ -13,7 +13,7 @@ unless ENV["CI"]
|
|
13
13
|
end
|
14
14
|
|
15
15
|
let(:concurrency) { 24 }
|
16
|
-
let(:
|
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
|
-
|
35
|
+
messages.times do
|
36
36
|
x.publish(body)
|
37
37
|
end
|
38
|
-
puts "Published #{
|
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.
|
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-
|
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
|