bunny 2.6.3 → 2.6.4

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