bunny 2.6.3 → 2.6.4

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -3
  3. data/ChangeLog.md +23 -2
  4. data/Gemfile +3 -3
  5. data/LICENSE +1 -1
  6. data/README.md +2 -2
  7. data/lib/bunny/channel.rb +1 -1
  8. data/lib/bunny/channel_id_allocator.rb +3 -3
  9. data/lib/bunny/concurrent/continuation_queue.rb +9 -5
  10. data/lib/bunny/exceptions.rb +6 -0
  11. data/lib/bunny/session.rb +69 -11
  12. data/lib/bunny/transport.rb +1 -1
  13. data/lib/bunny/version.rb +1 -1
  14. data/spec/higher_level_api/integration/basic_ack_spec.rb +46 -46
  15. data/spec/higher_level_api/integration/basic_cancel_spec.rb +13 -13
  16. data/spec/higher_level_api/integration/basic_consume_spec.rb +40 -40
  17. data/spec/higher_level_api/integration/basic_consume_with_objects_spec.rb +5 -5
  18. data/spec/higher_level_api/integration/basic_get_spec.rb +5 -5
  19. data/spec/higher_level_api/integration/basic_nack_spec.rb +13 -13
  20. data/spec/higher_level_api/integration/basic_publish_spec.rb +7 -7
  21. data/spec/higher_level_api/integration/basic_qos_spec.rb +1 -1
  22. data/spec/higher_level_api/integration/basic_reject_spec.rb +23 -23
  23. data/spec/higher_level_api/integration/basic_return_spec.rb +3 -3
  24. data/spec/higher_level_api/integration/channel_close_spec.rb +1 -1
  25. data/spec/higher_level_api/integration/channel_open_spec.rb +1 -1
  26. data/spec/higher_level_api/integration/connection_recovery_spec.rb +93 -55
  27. data/spec/higher_level_api/integration/connection_spec.rb +46 -46
  28. data/spec/higher_level_api/integration/connection_stop_spec.rb +9 -8
  29. data/spec/higher_level_api/integration/consumer_cancellation_notification_spec.rb +14 -14
  30. data/spec/higher_level_api/integration/dead_lettering_spec.rb +8 -8
  31. data/spec/higher_level_api/integration/exchange_bind_spec.rb +4 -4
  32. data/spec/higher_level_api/integration/exchange_declare_spec.rb +10 -10
  33. data/spec/higher_level_api/integration/exchange_delete_spec.rb +1 -1
  34. data/spec/higher_level_api/integration/exchange_unbind_spec.rb +3 -3
  35. data/spec/higher_level_api/integration/exclusive_queue_spec.rb +5 -5
  36. data/spec/higher_level_api/integration/heartbeat_spec.rb +4 -4
  37. data/spec/higher_level_api/integration/merry_go_round_spec.rb +10 -10
  38. data/spec/higher_level_api/integration/message_properties_access_spec.rb +22 -22
  39. data/spec/higher_level_api/integration/predeclared_exchanges_spec.rb +1 -1
  40. data/spec/higher_level_api/integration/publisher_confirms_spec.rb +8 -8
  41. data/spec/higher_level_api/integration/publishing_edge_cases_spec.rb +10 -10
  42. data/spec/higher_level_api/integration/queue_bind_spec.rb +10 -10
  43. data/spec/higher_level_api/integration/queue_declare_spec.rb +14 -11
  44. data/spec/higher_level_api/integration/queue_delete_spec.rb +1 -1
  45. data/spec/higher_level_api/integration/queue_purge_spec.rb +3 -3
  46. data/spec/higher_level_api/integration/queue_unbind_spec.rb +4 -4
  47. data/spec/higher_level_api/integration/read_only_consumer_spec.rb +7 -7
  48. data/spec/higher_level_api/integration/sender_selected_distribution_spec.rb +6 -6
  49. data/spec/higher_level_api/integration/tls_connection_spec.rb +40 -40
  50. data/spec/higher_level_api/integration/tx_commit_spec.rb +1 -1
  51. data/spec/higher_level_api/integration/tx_rollback_spec.rb +1 -1
  52. data/spec/higher_level_api/integration/with_channel_spec.rb +1 -1
  53. data/spec/issues/issue100_spec.rb +7 -7
  54. data/spec/issues/issue141_spec.rb +3 -3
  55. data/spec/issues/issue224_spec.rb +3 -3
  56. data/spec/issues/issue465_spec.rb +32 -0
  57. data/spec/issues/issue78_spec.rb +11 -10
  58. data/spec/issues/issue83_spec.rb +1 -1
  59. data/spec/issues/issue97_spec.rb +20 -20
  60. data/spec/stress/channel_close_stress_spec.rb +3 -3
  61. data/spec/stress/channel_open_stress_spec.rb +3 -3
  62. data/spec/stress/channel_open_stress_with_single_threaded_connection_spec.rb +2 -1
  63. data/spec/stress/concurrent_consumers_stress_spec.rb +6 -6
  64. data/spec/stress/concurrent_publishers_stress_spec.rb +2 -1
  65. data/spec/stress/connection_open_close_spec.rb +3 -3
  66. data/spec/stress/long_running_consumer_spec.rb +7 -5
  67. data/spec/unit/concurrent/condition_spec.rb +5 -5
  68. metadata +4 -6
  69. data/spec/higher_level_api/integration/basic_recover_spec.rb +0 -18
  70. data/spec/higher_level_api/integration/consistent_hash_exchange_spec.rb +0 -59
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe "Published message" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -15,12 +15,12 @@ describe "Published message" do
15
15
  it "routes the messages" do
16
16
  ch = connection.create_channel
17
17
 
18
- q = ch.queue("", :exclusive => true)
18
+ q = ch.queue("", exclusive: true)
19
19
  x = ch.fanout("amq.fanout")
20
20
  q.bind(x)
21
21
 
22
22
  rk = "a" * 254
23
- x.publish("xyzzy", :routing_key => rk, :persistent => true)
23
+ x.publish("xyzzy", routing_key: rk, persistent: true)
24
24
 
25
25
  sleep(1)
26
26
  expect(q.message_count).to eq 1
@@ -37,12 +37,12 @@ describe "Published message" do
37
37
  it "routes the messages" do
38
38
  ch = connection.create_channel
39
39
 
40
- q = ch.queue("", :exclusive => true)
40
+ q = ch.queue("", exclusive: true)
41
41
  x = ch.fanout("amq.fanout")
42
42
  q.bind(x)
43
43
 
44
44
  rk = "a" * 255
45
- x.publish("xyzzy", :routing_key => rk, :persistent => true)
45
+ x.publish("xyzzy", routing_key: rk, persistent: true)
46
46
 
47
47
  sleep(1)
48
48
  expect(q.message_count).to eq 1
@@ -59,13 +59,13 @@ describe "Published message" do
59
59
  it "fails with a connection exception" do
60
60
  ch = connection.create_channel
61
61
 
62
- q = ch.queue("", :exclusive => true)
62
+ q = ch.queue("", exclusive: true)
63
63
  x = ch.fanout("amq.fanout")
64
64
  q.bind(x)
65
65
 
66
66
  rk = "a" * 256
67
67
  expect do
68
- x.publish("xyzzy", :routing_key => rk, :persistent => true)
68
+ x.publish("xyzzy", routing_key: rk, persistent: true)
69
69
  end.to raise_error(ArgumentError)
70
70
 
71
71
  ch.close
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Channel, "#prefetch" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Channel, "#reject" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -14,13 +14,13 @@ describe Bunny::Channel, "#reject" do
14
14
  context "with requeue = true" do
15
15
  it "requeues a message" do
16
16
  ch = connection.create_channel
17
- q = ch.queue("bunny.basic.reject.manual-acks", :exclusive => true)
17
+ q = ch.queue("bunny.basic.reject.manual-acks", exclusive: true)
18
18
  x = ch.default_exchange
19
19
 
20
- x.publish("bunneth", :routing_key => q.name)
20
+ x.publish("bunneth", routing_key: q.name)
21
21
  sleep(0.5)
22
22
  expect(q.message_count).to eq 1
23
- delivery_info, _, _ = q.pop(:manual_ack => true)
23
+ delivery_info, _, _ = q.pop(manual_ack: true)
24
24
 
25
25
  ch.reject(delivery_info.delivery_tag, true)
26
26
  sleep(0.5)
@@ -33,20 +33,20 @@ describe Bunny::Channel, "#reject" do
33
33
  context "with requeue = false" do
34
34
  it "rejects a message" do
35
35
  ch = connection.create_channel
36
- q = ch.queue("bunny.basic.reject.with-requeue-false", :exclusive => true)
36
+ q = ch.queue("bunny.basic.reject.with-requeue-false", exclusive: true)
37
37
  x = ch.default_exchange
38
38
 
39
- x.publish("bunneth", :routing_key => q.name)
39
+ x.publish("bunneth", routing_key: q.name)
40
40
  sleep(0.5)
41
41
  expect(q.message_count).to eq 1
42
- delivery_info, _, _ = q.pop(:manual_ack => true)
42
+ delivery_info, _, _ = q.pop(manual_ack: true)
43
43
 
44
44
  ch.reject(delivery_info.delivery_tag, false)
45
45
  sleep(0.5)
46
46
  ch.close
47
47
 
48
48
  ch = connection.create_channel
49
- q = ch.queue("bunny.basic.reject.with-requeue-false", :exclusive => true)
49
+ q = ch.queue("bunny.basic.reject.with-requeue-false", exclusive: true)
50
50
  expect(q.message_count).to eq 0
51
51
  ch.close
52
52
  end
@@ -56,13 +56,13 @@ describe Bunny::Channel, "#reject" do
56
56
  context "with an invalid (random) delivery tag" do
57
57
  it "causes a channel-level error" do
58
58
  ch = connection.create_channel
59
- q = ch.queue("bunny.basic.reject.unknown-delivery-tag", :exclusive => true)
59
+ q = ch.queue("bunny.basic.reject.unknown-delivery-tag", exclusive: true)
60
60
  x = ch.default_exchange
61
61
 
62
- x.publish("bunneth", :routing_key => q.name)
62
+ x.publish("bunneth", routing_key: q.name)
63
63
  sleep(0.25)
64
64
  expect(q.message_count).to eq 1
65
- _, _, content = q.pop(:manual_ack => true)
65
+ _, _, content = q.pop(manual_ack: true)
66
66
 
67
67
  ch.on_error do |ch, channel_close|
68
68
  @channel_close = channel_close
@@ -78,7 +78,7 @@ end
78
78
 
79
79
  describe Bunny::Channel, "#basic_reject" do
80
80
  let(:connection) do
81
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
81
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
82
82
  c.start
83
83
  c
84
84
  end
@@ -90,13 +90,13 @@ describe Bunny::Channel, "#basic_reject" do
90
90
  context "with requeue = true" do
91
91
  it "requeues a message" do
92
92
  ch = connection.create_channel
93
- q = ch.queue("bunny.basic.reject.manual-acks", :exclusive => true)
93
+ q = ch.queue("bunny.basic.reject.manual-acks", exclusive: true)
94
94
  x = ch.default_exchange
95
95
 
96
- x.publish("bunneth", :routing_key => q.name)
96
+ x.publish("bunneth", routing_key: q.name)
97
97
  sleep(0.5)
98
98
  expect(q.message_count).to eq 1
99
- delivery_info, _, _ = q.pop(:manual_ack => true)
99
+ delivery_info, _, _ = q.pop(manual_ack: true)
100
100
 
101
101
  ch.basic_reject(delivery_info.delivery_tag.to_i, true)
102
102
  sleep(0.5)
@@ -109,20 +109,20 @@ describe Bunny::Channel, "#basic_reject" do
109
109
  context "with requeue = false" do
110
110
  it "rejects a message" do
111
111
  ch = connection.create_channel
112
- q = ch.queue("bunny.basic.reject.with-requeue-false", :exclusive => true)
112
+ q = ch.queue("bunny.basic.reject.with-requeue-false", exclusive: true)
113
113
  x = ch.default_exchange
114
114
 
115
- x.publish("bunneth", :routing_key => q.name)
115
+ x.publish("bunneth", routing_key: q.name)
116
116
  sleep(0.5)
117
117
  expect(q.message_count).to eq 1
118
- delivery_info, _, _ = q.pop(:manual_ack => true)
118
+ delivery_info, _, _ = q.pop(manual_ack: true)
119
119
 
120
120
  ch.basic_reject(delivery_info.delivery_tag.to_i, false)
121
121
  sleep(0.5)
122
122
  ch.close
123
123
 
124
124
  ch = connection.create_channel
125
- q = ch.queue("bunny.basic.reject.with-requeue-false", :exclusive => true)
125
+ q = ch.queue("bunny.basic.reject.with-requeue-false", exclusive: true)
126
126
  expect(q.message_count).to eq 0
127
127
  ch.close
128
128
  end
@@ -131,20 +131,20 @@ describe Bunny::Channel, "#basic_reject" do
131
131
  context "with requeue = default" do
132
132
  it "rejects a message" do
133
133
  ch = connection.create_channel
134
- q = ch.queue("bunny.basic.reject.with-requeue-false", :exclusive => true)
134
+ q = ch.queue("bunny.basic.reject.with-requeue-false", exclusive: true)
135
135
  x = ch.default_exchange
136
136
 
137
- x.publish("bunneth", :routing_key => q.name)
137
+ x.publish("bunneth", routing_key: q.name)
138
138
  sleep(0.5)
139
139
  expect(q.message_count).to eq 1
140
- delivery_info, _, _ = q.pop(:manual_ack => true)
140
+ delivery_info, _, _ = q.pop(manual_ack: true)
141
141
 
142
142
  ch.basic_reject(delivery_info.delivery_tag.to_i)
143
143
  sleep(0.5)
144
144
  ch.close
145
145
 
146
146
  ch = connection.create_channel
147
- q = ch.queue("bunny.basic.reject.with-requeue-false", :exclusive => true)
147
+ q = ch.queue("bunny.basic.reject.with-requeue-false", exclusive: true)
148
148
  expect(q.message_count).to eq 0
149
149
  ch.close
150
150
  end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Exchange, "#publish" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -12,7 +12,7 @@ describe Bunny::Exchange, "#publish" do
12
12
  end
13
13
 
14
14
 
15
- context "with :mandatory => true and a bad [no routes] routing key" do
15
+ context "with mandatory: true and a bad [no routes] routing key" do
16
16
  it "causes a message to be returned" do
17
17
  ch = connection.create_channel
18
18
  x = ch.default_exchange
@@ -22,7 +22,7 @@ describe Bunny::Exchange, "#publish" do
22
22
  returned << content
23
23
  end
24
24
 
25
- x.publish("xyzzy", :routing_key => rand.to_s, :mandatory => true)
25
+ x.publish("xyzzy", routing_key: rand.to_s, mandatory: true)
26
26
  sleep 0.5
27
27
 
28
28
  expect(returned).to include("xyzzy")
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Channel, "when closed" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe Bunny::Channel, "when opened" do
4
4
  let(:connection) do
5
- c = Bunny.new(:user => "bunny_gem", :password => "bunny_password", :vhost => "bunny_testbed")
5
+ c = Bunny.new(username: "bunny_gem", password: "bunny_password", vhost: "bunny_testbed")
6
6
  c.start
7
7
  c
8
8
  end
@@ -3,27 +3,27 @@ require "rabbitmq/http/client"
3
3
 
4
4
  describe "Connection recovery" do
5
5
  let(:http_client) { RabbitMQ::HTTP::Client.new("http://127.0.0.1:15672") }
6
- let(:logger) { Logger.new($stderr).tap {|logger| logger.level = Logger::FATAL} }
6
+ let(:logger) { Logger.new($stderr).tap {|logger| logger.level = ENV["BUNNY_LOG_LEVEL"] || Logger::WARN } }
7
7
  let(:recovery_interval) { 0.2 }
8
8
 
9
9
  it "reconnects after grace period" do
10
10
  with_open do |c|
11
11
  close_all_connections!
12
- wait_on_loss_and_recovery_of { connections.any? }
12
+ wait_for_recovery_with { connections.any? }
13
13
  end
14
14
  end
15
15
 
16
16
  it "reconnects after grace period (with multiple hosts)" do
17
17
  with_open_multi_host do |c|
18
18
  close_all_connections!
19
- wait_on_loss_and_recovery_of { connections.any? }
19
+ wait_for_recovery_with { connections.any? }
20
20
  end
21
21
  end
22
22
 
23
23
  it "reconnects after grace period (with multiple hosts, including a broken one)" do
24
24
  with_open_multi_broken_host do |c|
25
25
  close_all_connections!
26
- wait_on_loss_and_recovery_of { connections.any? }
26
+ wait_for_recovery_with { connections.any? }
27
27
  end
28
28
  end
29
29
 
@@ -31,8 +31,9 @@ describe "Connection recovery" do
31
31
  with_open do |c|
32
32
  ch1 = c.create_channel
33
33
  ch2 = c.create_channel
34
+ sleep 1.5
34
35
  close_all_connections!
35
- poll_until { channels.count.zero? }
36
+ sleep 0.5
36
37
  poll_until { channels.count == 2 }
37
38
  expect(ch1).to be_open
38
39
  expect(ch2).to be_open
@@ -43,8 +44,9 @@ describe "Connection recovery" do
43
44
  with_open_multi_host do |c|
44
45
  ch1 = c.create_channel
45
46
  ch2 = c.create_channel
47
+ sleep 1.5
46
48
  close_all_connections!
47
- poll_until { channels.count.zero? }
49
+ sleep 0.5
48
50
  poll_until { channels.count == 2 }
49
51
  expect(ch1).to be_open
50
52
  expect(ch2).to be_open
@@ -55,8 +57,9 @@ describe "Connection recovery" do
55
57
  with_open_multi_broken_host do |c|
56
58
  ch1 = c.create_channel
57
59
  ch2 = c.create_channel
60
+ sleep 1.5
58
61
  close_all_connections!
59
- poll_until { channels.count.zero? }
62
+ sleep 0.5
60
63
  poll_until { channels.count == 2 }
61
64
  expect(ch1).to be_open
62
65
  expect(ch2).to be_open
@@ -69,8 +72,10 @@ describe "Connection recovery" do
69
72
  ch.prefetch(11)
70
73
  expect(ch.prefetch_count).to eq 11
71
74
  expect(ch.prefetch_global).to be false
75
+ sleep 1.5
72
76
  close_all_connections!
73
- wait_on_loss_and_recovery_of { connections.any? }
77
+ sleep 0.5
78
+ wait_for_recovery_with { connections.any? }
74
79
  expect(ch).to be_open
75
80
  expect(ch.prefetch_count).to eq 11
76
81
  expect(ch.prefetch_global).to be false
@@ -83,8 +88,10 @@ describe "Connection recovery" do
83
88
  ch.prefetch(42, true)
84
89
  expect(ch.prefetch_count).to eq 42
85
90
  expect(ch.prefetch_global).to be true
91
+ sleep 1.5
86
92
  close_all_connections!
87
- wait_on_loss_and_recovery_of { connections.any? }
93
+ sleep 0.5
94
+ wait_for_recovery_with { connections.any? }
88
95
  expect(ch).to be_open
89
96
  expect(ch.prefetch_count).to eq 42
90
97
  expect(ch.prefetch_global).to be true
@@ -96,8 +103,10 @@ describe "Connection recovery" do
96
103
  ch = c.create_channel
97
104
  ch.confirm_select
98
105
  expect(ch).to be_using_publisher_confirms
106
+ sleep 1.5
99
107
  close_all_connections!
100
- wait_on_loss_and_recovery_of { connections.any? }
108
+ sleep 0.5
109
+ wait_for_recovery_with { connections.any? }
101
110
  expect(ch).to be_open
102
111
  expect(ch).to be_using_publisher_confirms
103
112
  end
@@ -108,8 +117,10 @@ describe "Connection recovery" do
108
117
  ch = c.create_channel
109
118
  ch.tx_select
110
119
  expect(ch).to be_using_tx
120
+ sleep 1.5
111
121
  close_all_connections!
112
- wait_on_loss_and_recovery_of { connections.any? }
122
+ sleep 0.5
123
+ wait_for_recovery_with { connections.any? }
113
124
  expect(ch).to be_open
114
125
  expect(ch).to be_using_tx
115
126
  end
@@ -120,15 +131,15 @@ describe "Connection recovery" do
120
131
  ch = c.create_channel
121
132
  q = ch.queue("bunny.tests.recovery.client-named#{rand}")
122
133
  close_all_connections!
123
- wait_on_loss_and_recovery_of { connections.any? }
134
+ wait_for_recovery_with { connections.any? }
124
135
  expect(ch).to be_open
125
136
  ensure_queue_recovery(ch, q)
126
137
  q.delete
127
138
  end
128
139
  end
129
140
 
130
- # a very simplistic test for queues inspired by #412
131
- it "recovers client-named queues declared with passive = true" do
141
+ # a very simplistic test for queues inspired by #422
142
+ it "recovers client-named queues declared with no_declare: true" do
132
143
  with_open do |c|
133
144
  ch = c.create_channel
134
145
  ch2 = c.create_channel
@@ -140,20 +151,40 @@ describe "Connection recovery" do
140
151
  q2 = ch2.queue(s, no_declare: true)
141
152
 
142
153
  close_all_connections!
143
- wait_on_loss_and_recovery_of { connections.any? }
154
+ wait_for_recovery_with { connections.any? }
144
155
  expect(ch).to be_open
145
156
  ensure_queue_recovery(ch, q)
146
157
  q.delete
147
158
  end
148
159
  end
149
160
 
161
+ # a test for #422
162
+ it "recovers client-named queues declared with passive: true" do
163
+ with_open do |c|
164
+ ch = c.create_channel
165
+ ch2 = c.create_channel
166
+
167
+ n = rand
168
+ s = "bunny.tests.recovery.client-named#{n}"
169
+
170
+ q = ch.queue(s)
171
+ q2 = ch2.queue(s, passive: true)
172
+
173
+ close_all_connections!
174
+ wait_for_recovery_with { connections.any? }
175
+ expect(ch).to be_open
176
+ ensure_queue_recovery(ch, q)
177
+ ensure_queue_recovery(ch, q2)
178
+ q.delete
179
+ end
180
+ end
150
181
 
151
182
  it "recovers server-named queues" do
152
183
  with_open do |c|
153
184
  ch = c.create_channel
154
- q = ch.queue("", :exclusive => true)
185
+ q = ch.queue("", exclusive: true)
155
186
  close_all_connections!
156
- wait_on_loss_and_recovery_of { connections.any? }
187
+ wait_for_recovery_with { connections.any? }
157
188
  expect(ch).to be_open
158
189
  ensure_queue_recovery(ch, q)
159
190
  end
@@ -163,10 +194,10 @@ describe "Connection recovery" do
163
194
  with_open do |c|
164
195
  ch = c.create_channel
165
196
  x = ch.fanout("amq.fanout")
166
- q = ch.queue("", :exclusive => true)
197
+ q = ch.queue("", exclusive: true)
167
198
  q.bind(x)
168
199
  close_all_connections!
169
- wait_on_loss_and_recovery_of { connections.any? }
200
+ wait_for_recovery_with { connections.any? }
170
201
  expect(ch).to be_open
171
202
  ensure_queue_binding_recovery(ch, x, q)
172
203
  end
@@ -190,13 +221,43 @@ describe "Connection recovery" do
190
221
 
191
222
  close_all_connections!
192
223
 
193
- wait_on_loss_and_recovery_of { exchange_names_in_vhost("/").include?(source.name) }
224
+ wait_for_recovery_with { exchange_names_in_vhost("/").include?(source.name) }
225
+ ch.confirm_select
194
226
 
227
+ source.publish("msg", routing_key: "")
228
+ ch.wait_for_confirms
229
+ expect(dst_queue.message_count).to eq 1
230
+ destination.delete
231
+ end
232
+ end
233
+
234
+ it "recovers passively declared exchanges and their bindings" do
235
+ with_open do |c|
236
+ ch = c.create_channel
195
237
  ch.confirm_select
196
238
 
239
+ source = ch.fanout("amq.fanout", passive: true)
240
+ destination = ch.fanout("destination.exchange.recovery.example", auto_delete: true)
241
+
242
+ destination.bind(source)
243
+
244
+ # Exchanges won't get auto-deleted on connection loss unless they have
245
+ # had an exclusive queue bound to them.
246
+ dst_queue = ch.queue("", exclusive: true)
247
+ dst_queue.bind(destination, routing_key: "")
248
+
249
+ src_queue = ch.queue("", exclusive: true)
250
+ src_queue.bind(source, routing_key: "")
251
+
252
+ close_all_connections!
253
+
254
+ wait_for_recovery_with { connections.any? }
255
+
197
256
  source.publish("msg", routing_key: "")
198
257
  ch.wait_for_confirms
258
+
199
259
  expect(dst_queue.message_count).to eq 1
260
+ destination.delete
200
261
  end
201
262
  end
202
263
 
@@ -223,7 +284,7 @@ describe "Connection recovery" do
223
284
 
224
285
  close_all_connections!
225
286
 
226
- wait_on_loss_and_recovery_of { exchange_names_in_vhost("/").include?(source.name) }
287
+ wait_for_recovery_with { exchange_names_in_vhost("/").include?(source.name) }
227
288
 
228
289
  ch2.confirm_select
229
290
 
@@ -239,7 +300,7 @@ describe "Connection recovery" do
239
300
  10.times { c.create_channel }
240
301
  expect(c.queue_exists?(q)).to eq false
241
302
  close_all_connections!
242
- wait_on_loss_and_recovery_of { channels.any? }
303
+ wait_for_recovery_with { channels.any? }
243
304
  # make sure the connection isn't closed shortly after
244
305
  # due to "second 'channel.open' seen". MK.
245
306
  expect(c).to be_open
@@ -255,12 +316,12 @@ describe "Connection recovery" do
255
316
  delivered = false
256
317
 
257
318
  ch = c.create_channel
258
- q = ch.queue("", :exclusive => true)
319
+ q = ch.queue("", exclusive: true)
259
320
  q.subscribe do |_, _, _|
260
321
  delivered = true
261
322
  end
262
323
  close_all_connections!
263
- wait_on_loss_and_recovery_of { connections.any? }
324
+ wait_for_recovery_with { connections.any? }
264
325
  expect(ch).to be_open
265
326
 
266
327
  q.publish("")
@@ -274,10 +335,10 @@ describe "Connection recovery" do
274
335
 
275
336
  with_open do |c|
276
337
  ch = c.create_channel
277
- q = ch.queue("", :exclusive => true)
338
+ q = ch.queue("", exclusive: true)
278
339
  n.times { q.subscribe { |_, _, _| } }
279
340
  close_all_connections!
280
- wait_on_loss_and_recovery_of { connections.any? }
341
+ wait_for_recovery_with { connections.any? }
281
342
  expect(ch).to be_open
282
343
  sleep 0.5
283
344
 
@@ -294,34 +355,19 @@ describe "Connection recovery" do
294
355
  ch = c.create_channel
295
356
 
296
357
  n.times do
297
- qs << ch.queue("", :exclusive => true)
358
+ qs << ch.queue("", exclusive: true)
298
359
  end
299
360
  close_all_connections!
300
- wait_on_loss_and_recovery_of { queue_names.include?(qs.first.name) }
361
+ wait_for_recovery_with { queue_names.include?(qs.first.name) }
301
362
  sleep 0.5
302
363
  expect(ch).to be_open
303
364
 
304
365
  qs.each do |q|
305
- ch.queue_declare(q.name, :passive => true)
366
+ ch.queue_declare(q.name, passive: true)
306
367
  end
307
368
  end
308
369
  end
309
370
 
310
- it "tries to recover for a given number of attempts" do
311
- pending "Need a fix for https://github.com/ruby-amqp/bunny/issues/408"
312
- with_recovery_attempts_limited_to(2) do |c|
313
- close_all_connections!
314
- wait_on_loss_and_recovery_of { connections.any? }
315
-
316
- close_all_connections!
317
- wait_on_loss_and_recovery_of { connections.any? }
318
-
319
- close_all_connections!
320
- sleep(recovery_interval + 0.5)
321
- expect(connections).to be_empty
322
- end
323
- end
324
-
325
371
  def exchange_names_in_vhost(vhost)
326
372
  http_client.list_exchanges(vhost).map {|e| e["name"]}
327
373
  end
@@ -346,11 +392,11 @@ describe "Connection recovery" do
346
392
 
347
393
  def close_ignoring_permitted_exceptions(connection_name)
348
394
  http_client.close_connection(connection_name)
349
- rescue Bunny::ConnectionForced
395
+ rescue Bunny::ConnectionForced, Faraday::ResourceNotFound
396
+ # ignored
350
397
  end
351
398
 
352
- def wait_on_loss_and_recovery_of(&probe)
353
- poll_while &probe
399
+ def wait_for_recovery_with(&probe)
354
400
  poll_until &probe
355
401
  end
356
402
 
@@ -392,14 +438,6 @@ describe "Connection recovery" do
392
438
  with_open(c, &block)
393
439
  end
394
440
 
395
- def with_recovery_attempts_limited_to(attempts = 3, &block)
396
- c = Bunny.new(recover_from_connection_close: true,
397
- network_recovery_interval: recovery_interval,
398
- recovery_attempts: attempts,
399
- logger: logger)
400
- with_open(c, &block)
401
- end
402
-
403
441
  def ensure_queue_recovery(ch, q)
404
442
  ch.confirm_select
405
443
  q.purge