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 +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
|