ably 0.8.5 → 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +42 -48
- data/SPEC.md +1099 -640
- data/ably.gemspec +10 -4
- data/lib/ably/auth.rb +155 -47
- data/lib/ably/exceptions.rb +2 -0
- data/lib/ably/models/channel_state_change.rb +2 -3
- data/lib/ably/models/connection_details.rb +54 -0
- data/lib/ably/models/protocol_message.rb +14 -4
- data/lib/ably/models/token_details.rb +13 -7
- data/lib/ably/models/token_request.rb +1 -2
- data/lib/ably/modules/ably.rb +3 -2
- data/lib/ably/modules/message_emitter.rb +1 -3
- data/lib/ably/modules/state_emitter.rb +2 -2
- data/lib/ably/realtime/auth.rb +6 -0
- data/lib/ably/realtime/channel/channel_manager.rb +2 -0
- data/lib/ably/realtime/channel.rb +15 -4
- data/lib/ably/realtime/client/incoming_message_dispatcher.rb +11 -1
- data/lib/ably/realtime/client.rb +10 -3
- data/lib/ably/realtime/connection/connection_manager.rb +58 -54
- data/lib/ably/realtime/connection.rb +62 -6
- data/lib/ably/realtime/presence.rb +18 -5
- data/lib/ably/rest/channel.rb +9 -1
- data/lib/ably/rest/client.rb +32 -14
- data/lib/ably/rest/presence.rb +1 -1
- data/lib/ably/version.rb +1 -1
- data/lib/ably.rb +2 -0
- data/spec/acceptance/realtime/auth_spec.rb +251 -11
- data/spec/acceptance/realtime/channel_history_spec.rb +12 -2
- data/spec/acceptance/realtime/channel_spec.rb +316 -24
- data/spec/acceptance/realtime/client_spec.rb +93 -1
- data/spec/acceptance/realtime/connection_failures_spec.rb +177 -86
- data/spec/acceptance/realtime/connection_spec.rb +284 -60
- data/spec/acceptance/realtime/message_spec.rb +45 -6
- data/spec/acceptance/realtime/presence_history_spec.rb +4 -0
- data/spec/acceptance/realtime/presence_spec.rb +181 -49
- data/spec/acceptance/realtime/time_spec.rb +13 -0
- data/spec/acceptance/rest/auth_spec.rb +222 -4
- data/spec/acceptance/rest/channel_spec.rb +132 -1
- data/spec/acceptance/rest/client_spec.rb +129 -28
- data/spec/acceptance/rest/presence_spec.rb +7 -7
- data/spec/acceptance/rest/time_spec.rb +10 -0
- data/spec/shared/client_initializer_behaviour.rb +41 -17
- data/spec/spec_helper.rb +1 -0
- data/spec/support/debug_failure_helper.rb +16 -0
- data/spec/unit/models/connection_details_spec.rb +60 -0
- data/spec/unit/models/protocol_message_spec.rb +45 -0
- data/spec/unit/modules/event_emitter_spec.rb +3 -1
- data/spec/unit/realtime/channel_spec.rb +6 -5
- data/spec/unit/realtime/client_spec.rb +5 -1
- data/spec/unit/realtime/connection_spec.rb +5 -1
- data/spec/unit/realtime/realtime_spec.rb +5 -1
- metadata +54 -7
@@ -53,19 +53,17 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
context 'automatic connection retry' do
|
56
|
-
let(:client_failure_options) { default_options.merge(log_level: :none) }
|
57
|
-
|
58
56
|
context 'with invalid WebSocket host' do
|
59
57
|
let(:retry_every_for_tests) { 0.2 }
|
60
58
|
let(:max_time_in_state_for_tests) { 0.6 }
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
60
|
+
let(:client_failure_options) do
|
61
|
+
default_options.merge(
|
62
|
+
log_level: :none,
|
63
|
+
disconnected_retry_timeout: retry_every_for_tests,
|
64
|
+
suspended_retry_timeout: retry_every_for_tests,
|
65
|
+
connection_state_ttl: max_time_in_state_for_tests
|
66
|
+
)
|
69
67
|
end
|
70
68
|
|
71
69
|
# retry immediately after failure, then one retry every :retry_every_for_tests
|
@@ -110,6 +108,27 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
110
108
|
end
|
111
109
|
end
|
112
110
|
|
111
|
+
context 'for the first time' do
|
112
|
+
let(:client_options) do
|
113
|
+
default_options.merge(realtime_host: 'non.existent.host', disconnected_retry_timeout: 2, log_level: :error)
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'reattempts connection immediately and then waits disconnected_retry_timeout for a subsequent attempt' do
|
117
|
+
expect(connection.defaults[:disconnected_retry_timeout]).to eql(2)
|
118
|
+
connection.once(:disconnected) do
|
119
|
+
started_at = Time.now.to_f
|
120
|
+
connection.once(:disconnected) do
|
121
|
+
expect(Time.now.to_f - started_at).to be < 1
|
122
|
+
started_at = Time.now.to_f
|
123
|
+
connection.once(:disconnected) do
|
124
|
+
expect(Time.now.to_f - started_at).to be > 2
|
125
|
+
stop_reactor
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
113
132
|
describe '#close' do
|
114
133
|
it 'transitions connection state to :closed' do
|
115
134
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
@@ -130,25 +149,50 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
130
149
|
end
|
131
150
|
|
132
151
|
context 'when connection state is :suspended' do
|
133
|
-
it '
|
152
|
+
it 'stays in the suspended state after any number of reconnection attempts' do
|
134
153
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
135
154
|
|
136
155
|
connection.once(:suspended) do
|
137
156
|
count_state_changes && start_timer
|
138
157
|
|
139
|
-
|
140
|
-
expect(connection.state).to eq(:
|
158
|
+
EventMachine.add_timer((retry_every_for_tests + 0.1) * 10) do
|
159
|
+
expect(connection.state).to eq(:suspended)
|
141
160
|
|
142
|
-
expect(state_changes[:connecting]).to
|
143
|
-
expect(state_changes[:suspended]).to
|
161
|
+
expect(state_changes[:connecting]).to be >= 10
|
162
|
+
expect(state_changes[:suspended]).to be >= 10
|
144
163
|
expect(state_changes[:disconnected]).to eql(0)
|
145
164
|
|
146
|
-
expect(time_passed).to be > max_time_in_state_for_tests
|
147
165
|
stop_reactor
|
148
166
|
end
|
149
167
|
end
|
150
168
|
end
|
151
169
|
|
170
|
+
context 'for the first time' do
|
171
|
+
let(:client_options) do
|
172
|
+
default_options.merge(suspended_retry_timeout: 2, connection_state_ttl: 0, log_level: :error)
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'waits suspended_retry_timeout before attempting to reconnect' do
|
176
|
+
expect(client.connection.defaults[:suspended_retry_timeout]).to eql(2)
|
177
|
+
connection.once(:connected) do
|
178
|
+
connection.transition_state_machine :suspended
|
179
|
+
allow(connection).to receive(:current_host).and_return('does.not.exist.com')
|
180
|
+
|
181
|
+
started_at = Time.now.to_f
|
182
|
+
connection.once(:connecting) do
|
183
|
+
expect(Time.now.to_f - started_at).to be > 1.75
|
184
|
+
started_at = Time.now.to_f
|
185
|
+
connection.once(:connecting) do
|
186
|
+
expect(Time.now.to_f - started_at).to be > 1.75
|
187
|
+
connection.once(:suspended) do
|
188
|
+
stop_reactor
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
152
196
|
describe '#close' do
|
153
197
|
it 'transitions connection state to :closed' do
|
154
198
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
@@ -172,6 +216,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
172
216
|
it 'will not transition state to :close and raises a InvalidStateChange exception' do
|
173
217
|
connection.on(:connected) { raise 'Connection should not have reached :connected state' }
|
174
218
|
|
219
|
+
connection.once(:suspended) do
|
220
|
+
connection.transition_state_machine :failed
|
221
|
+
end
|
222
|
+
|
175
223
|
connection.once(:failed) do
|
176
224
|
expect(connection.state).to eq(:failed)
|
177
225
|
expect { connection.close }.to raise_error Ably::Exceptions::InvalidStateChange, /Unable to transition from failed => closing/
|
@@ -190,6 +238,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
190
238
|
expect(connection.error_reason.code).to eql(80000)
|
191
239
|
stop_reactor
|
192
240
|
end
|
241
|
+
|
242
|
+
connection.once(:suspended) do |connection_state_change|
|
243
|
+
connection.transition_state_machine :failed, reason: connection_state_change.reason
|
244
|
+
end
|
193
245
|
end
|
194
246
|
end
|
195
247
|
|
@@ -216,12 +268,16 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
216
268
|
end
|
217
269
|
|
218
270
|
describe '#connect' do
|
219
|
-
let(:
|
271
|
+
let(:timeout) { 1.5 }
|
220
272
|
|
221
|
-
|
222
|
-
|
223
|
-
|
273
|
+
let(:client_options) do
|
274
|
+
default_options.merge(
|
275
|
+
log_level: :none,
|
276
|
+
realtime_request_timeout: timeout
|
277
|
+
)
|
278
|
+
end
|
224
279
|
|
280
|
+
before do
|
225
281
|
connection.on(:connected) { raise "Connection should not open in this test as CONNECTED ProtocolMessage is never received" }
|
226
282
|
|
227
283
|
connection.once(:connecting) do
|
@@ -231,13 +287,11 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
231
287
|
end
|
232
288
|
|
233
289
|
context 'connection opening times out' do
|
234
|
-
let(:client_options) { client_failure_options }
|
235
|
-
|
236
290
|
it 'attempts to reconnect' do
|
237
291
|
started_at = Time.now
|
238
292
|
|
239
293
|
connection.once(:disconnected) do
|
240
|
-
expect(Time.now.to_f - started_at.to_f).to be >
|
294
|
+
expect(Time.now.to_f - started_at.to_f).to be > timeout
|
241
295
|
connection.once(:connecting) do
|
242
296
|
stop_reactor
|
243
297
|
end
|
@@ -246,21 +300,15 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
246
300
|
connection.connect
|
247
301
|
end
|
248
302
|
|
249
|
-
it 'calls the errback of the returned Deferrable object when first connection attempt fails' do
|
250
|
-
connection.connect.errback do |error|
|
251
|
-
expect(connection.state).to eq(:disconnected)
|
252
|
-
stop_reactor
|
253
|
-
end
|
254
|
-
end
|
255
|
-
|
256
303
|
context 'when retry intervals are stubbed to attempt reconnection quickly' do
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
304
|
+
let(:client_options) do
|
305
|
+
default_options.merge(
|
306
|
+
log_level: :error,
|
307
|
+
disconnected_retry_timeout: 0.1,
|
308
|
+
suspended_retry_timeout: 0.1,
|
309
|
+
connection_state_ttl: 0.2,
|
310
|
+
realtime_host: 'non.existent.host'
|
311
|
+
)
|
264
312
|
end
|
265
313
|
|
266
314
|
it 'never calls the provided success block', em_timeout: 10 do
|
@@ -268,8 +316,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
268
316
|
raise 'success block should not have been called'
|
269
317
|
end
|
270
318
|
|
271
|
-
connection.once(:
|
272
|
-
|
319
|
+
connection.once(:suspended) do
|
320
|
+
connection.once(:suspended) do
|
321
|
+
stop_reactor
|
322
|
+
end
|
273
323
|
end
|
274
324
|
end
|
275
325
|
end
|
@@ -315,14 +365,16 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
315
365
|
context 'and subsequently fails to reconnect' do
|
316
366
|
let(:retry_every) { 1.5 }
|
317
367
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
368
|
+
let(:client_options) do
|
369
|
+
default_options.merge(
|
370
|
+
log_level: :none,
|
371
|
+
disconnected_retry_timeout: retry_every,
|
372
|
+
suspended_retry_timeout: retry_every,
|
373
|
+
connection_state_ttl: 60
|
374
|
+
)
|
323
375
|
end
|
324
376
|
|
325
|
-
it "retries every #{Ably::Realtime::Connection::
|
377
|
+
it "retries every #{Ably::Realtime::Connection::DEFAULTS.fetch(:disconnected_retry_timeout)} seconds" do
|
326
378
|
fail_if_suspended_or_failed
|
327
379
|
|
328
380
|
stubbed_first_attempt = false
|
@@ -382,26 +434,52 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
382
434
|
end
|
383
435
|
|
384
436
|
context 'after successfully reconnecting and resuming' do
|
385
|
-
it 'retains connection_id and connection_key' do
|
386
|
-
previous_connection_id = nil
|
387
|
-
previous_connection_key = nil
|
388
|
-
|
437
|
+
it 'retains connection_id and updates the connection_key' do
|
389
438
|
connection.once(:connected) do
|
390
|
-
previous_connection_id
|
391
|
-
previous_connection_key = connection.key
|
439
|
+
previous_connection_id = connection.id
|
392
440
|
connection.transport.close_connection_after_writing
|
393
441
|
|
442
|
+
expect(connection).to receive(:configure_new).with(previous_connection_id, anything, anything).and_call_original
|
443
|
+
|
394
444
|
connection.once(:connected) do
|
395
|
-
|
396
|
-
# wVIsgTHAB1UvXh7z-1991d8586 becomes wVIsgTHAB1UvXh7z-1990d8586 after resume
|
397
|
-
expect(connection.key[/^\w{5,}-/, 0]).to_not be_nil
|
398
|
-
expect(connection.key[/^\w{5,}-/, 0]).to eql(previous_connection_key[/^\w{5,}-/, 0])
|
445
|
+
expect(connection.key).to_not be_nil
|
399
446
|
expect(connection.id).to eql(previous_connection_id)
|
400
447
|
stop_reactor
|
401
448
|
end
|
402
449
|
end
|
403
450
|
end
|
404
451
|
|
452
|
+
it 'emits any error received from Ably but leaves the channels attached' do
|
453
|
+
emitted_error = nil
|
454
|
+
channel.attach do
|
455
|
+
connection.transport.close_connection_after_writing
|
456
|
+
|
457
|
+
connection.once(:connecting) do
|
458
|
+
connection.__incoming_protocol_msgbus__.unsubscribe
|
459
|
+
connection.__incoming_protocol_msgbus__.subscribe(:protocol_message) do |protocol_message|
|
460
|
+
allow(protocol_message).to receive(:error).and_return(Ably::Exceptions::Standard.new('Injected error'))
|
461
|
+
end
|
462
|
+
# Create a new message dispatcher that subscribes to ProtocolMessages after the previous subscription allowing us
|
463
|
+
# to modify the ProtocolMessage
|
464
|
+
Ably::Realtime::Client::IncomingMessageDispatcher.new(client, connection)
|
465
|
+
end
|
466
|
+
|
467
|
+
connection.once(:connected) do
|
468
|
+
EM.add_timer(0.5) do
|
469
|
+
expect(emitted_error).to be_a(Ably::Exceptions::Standard)
|
470
|
+
expect(emitted_error.message).to match(/Injected error/)
|
471
|
+
expect(connection.error_reason).to be_a(Ably::Exceptions::Standard)
|
472
|
+
expect(channel).to be_attached
|
473
|
+
stop_reactor
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
connection.once(:error) do |error|
|
478
|
+
emitted_error = error
|
479
|
+
end
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
405
483
|
it 'retains channel subscription state' do
|
406
484
|
messages_received = false
|
407
485
|
|
@@ -527,27 +605,28 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
527
605
|
end
|
528
606
|
|
529
607
|
describe 'fallback host feature' do
|
530
|
-
let(:retry_every_for_tests) { 0.
|
531
|
-
let(:max_time_in_state_for_tests) { 0.
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
608
|
+
let(:retry_every_for_tests) { 0.2 }
|
609
|
+
let(:max_time_in_state_for_tests) { 0.59 }
|
610
|
+
|
611
|
+
let(:timeout_options) do
|
612
|
+
default_options.merge(
|
613
|
+
environment: :production,
|
614
|
+
log_level: :none,
|
615
|
+
disconnected_retry_timeout: retry_every_for_tests,
|
616
|
+
suspended_retry_timeout: retry_every_for_tests,
|
617
|
+
connection_state_ttl: max_time_in_state_for_tests
|
618
|
+
)
|
540
619
|
end
|
541
620
|
|
542
621
|
# Retry immediately and then wait retry_every before every subsequent attempt
|
543
|
-
let(:expected_retry_attempts)
|
622
|
+
let(:expected_retry_attempts) { 1 + (max_time_in_state_for_tests / retry_every_for_tests).round }
|
544
623
|
|
545
624
|
let(:retry_count_for_one_state) { 1 + expected_retry_attempts } # initial connect then disconnected
|
546
|
-
let(:retry_count_for_all_states) { 1 + expected_retry_attempts
|
625
|
+
let(:retry_count_for_all_states) { 1 + expected_retry_attempts + 1 } # initial connection, disconnected & then one suspended attempt
|
547
626
|
|
548
627
|
context 'with custom realtime websocket host option' do
|
549
628
|
let(:expected_host) { 'this.host.does.not.exist' }
|
550
|
-
let(:client_options) {
|
629
|
+
let(:client_options) { timeout_options.merge(realtime_host: expected_host) }
|
551
630
|
|
552
631
|
it 'never uses a fallback host' do
|
553
632
|
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host|
|
@@ -555,15 +634,17 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
555
634
|
raise EventMachine::ConnectionError
|
556
635
|
end
|
557
636
|
|
558
|
-
connection.
|
559
|
-
|
637
|
+
connection.once(:suspended) do
|
638
|
+
connection.once(:suspended) do
|
639
|
+
stop_reactor
|
640
|
+
end
|
560
641
|
end
|
561
642
|
end
|
562
643
|
end
|
563
644
|
|
564
645
|
context 'with custom realtime websocket port option' do
|
565
646
|
let(:custom_port) { 666}
|
566
|
-
let(:client_options) {
|
647
|
+
let(:client_options) { timeout_options.merge(tls_port: custom_port) }
|
567
648
|
|
568
649
|
it 'never uses a fallback host' do
|
569
650
|
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host, port|
|
@@ -571,8 +652,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
571
652
|
raise EventMachine::ConnectionError
|
572
653
|
end
|
573
654
|
|
574
|
-
connection.
|
575
|
-
|
655
|
+
connection.once(:suspended) do
|
656
|
+
connection.once(:suspended) do
|
657
|
+
stop_reactor
|
658
|
+
end
|
576
659
|
end
|
577
660
|
end
|
578
661
|
end
|
@@ -580,7 +663,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
580
663
|
context 'with non-production environment' do
|
581
664
|
let(:environment) { 'sandbox' }
|
582
665
|
let(:expected_host) { "#{environment}-#{Ably::Realtime::Client::DOMAIN}" }
|
583
|
-
let(:client_options) {
|
666
|
+
let(:client_options) { timeout_options.merge(environment: environment) }
|
584
667
|
|
585
668
|
it 'never uses a fallback host' do
|
586
669
|
expect(EventMachine).to receive(:connect).exactly(retry_count_for_all_states).times do |host|
|
@@ -588,8 +671,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
588
671
|
raise EventMachine::ConnectionError
|
589
672
|
end
|
590
673
|
|
591
|
-
connection.
|
592
|
-
|
674
|
+
connection.once(:suspended) do
|
675
|
+
connection.once(:suspended) do
|
676
|
+
stop_reactor
|
677
|
+
end
|
593
678
|
end
|
594
679
|
end
|
595
680
|
end
|
@@ -601,7 +686,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
601
686
|
end
|
602
687
|
|
603
688
|
let(:expected_host) { Ably::Realtime::Client::DOMAIN }
|
604
|
-
let(:client_options) {
|
689
|
+
let(:client_options) { timeout_options.merge(environment: nil) }
|
605
690
|
|
606
691
|
let(:fallback_hosts_used) { Array.new }
|
607
692
|
|
@@ -616,8 +701,10 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
616
701
|
raise EventMachine::ConnectionError
|
617
702
|
end
|
618
703
|
|
619
|
-
connection.
|
620
|
-
|
704
|
+
connection.once(:suspended) do
|
705
|
+
connection.once(:suspended) do
|
706
|
+
stop_reactor
|
707
|
+
end
|
621
708
|
end
|
622
709
|
end
|
623
710
|
end
|
@@ -629,8 +716,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
629
716
|
|
630
717
|
it 'uses a fallback host on every subsequent disconnected attempt until suspended' do
|
631
718
|
request = 0
|
632
|
-
|
633
|
-
expect(EventMachine).to receive(:connect).exactly(retry_count_for_one_state + 1).times do |host|
|
719
|
+
expect(EventMachine).to receive(:connect).exactly(retry_count_for_one_state).times do |host|
|
634
720
|
if request == 0
|
635
721
|
expect(host).to eql(expected_host)
|
636
722
|
else
|
@@ -640,7 +726,7 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
640
726
|
raise EventMachine::ConnectionError
|
641
727
|
end
|
642
728
|
|
643
|
-
connection.
|
729
|
+
connection.once(:suspended) do
|
644
730
|
fallback_hosts_used.pop # remove suspended attempt host
|
645
731
|
expect(fallback_hosts_used.uniq).to match_array(custom_hosts)
|
646
732
|
stop_reactor
|
@@ -649,20 +735,25 @@ describe Ably::Realtime::Connection, 'failures', :event_machine do
|
|
649
735
|
|
650
736
|
it 'uses the primary host when suspended, and a fallback host on every subsequent suspended attempt' do
|
651
737
|
request = 0
|
652
|
-
expect(EventMachine).to receive(:connect).
|
738
|
+
expect(EventMachine).to receive(:connect).at_least(:once) do |host|
|
653
739
|
if request == 0 || request == expected_retry_attempts + 1
|
654
740
|
expect(host).to eql(expected_host)
|
655
741
|
else
|
656
742
|
expect(custom_hosts).to include(host)
|
657
|
-
fallback_hosts_used << host
|
743
|
+
fallback_hosts_used << host if @suspended
|
658
744
|
end
|
659
745
|
request += 1
|
660
746
|
raise EventMachine::ConnectionError
|
661
747
|
end
|
662
748
|
|
663
|
-
connection.on(:
|
664
|
-
|
665
|
-
|
749
|
+
connection.on(:suspended) do
|
750
|
+
@suspended ||= 0
|
751
|
+
@suspended += 1
|
752
|
+
|
753
|
+
if @suspended > 3
|
754
|
+
expect(fallback_hosts_used.uniq).to match_array(custom_hosts)
|
755
|
+
stop_reactor
|
756
|
+
end
|
666
757
|
end
|
667
758
|
end
|
668
759
|
end
|