Skip to content

Commit bf791dd

Browse files
wip don't use fallback hosts on Realtime token errors
we seem to have it for REST — see line 616 of lib/ably/rest/client.rb
1 parent 9db3a61 commit bf791dd

4 files changed

Lines changed: 63 additions & 3 deletions

File tree

lib/ably/realtime/connection.rb

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,17 +391,26 @@ def __incoming_protocol_msgbus__
391391
def determine_host
392392
raise ArgumentError, 'Block required' unless block_given?
393393

394+
@determine_host_call_count ||= 0
395+
@determine_host_call_count += 1
396+
397+
if @determine_host_call_count == 3
398+
logger.debug { "LAWRENCE: On #{@determine_host_call_count} call to determine_host" }
399+
end
400+
394401
if should_use_fallback_hosts?
395402
internet_up? do |internet_is_up_result|
396403
@current_host = if internet_is_up_result
397404
client.fallback_endpoint.host
398405
else
399406
client.endpoint.host
400407
end
408+
logger.debug { "LAWRENCE: current_host from fallbacks: #{current_host}" }
401409
yield current_host
402410
end
403411
else
404412
@current_host = client.endpoint.host
413+
logger.debug { "LAWRENCE: current_host from not fallbacks: #{current_host}" }
405414
yield current_host
406415
end
407416
end
@@ -674,6 +683,17 @@ def custom_host?
674683
end
675684

676685
def should_use_fallback_hosts?
686+
logger.debug { "LAWRENCE: should_use_fallback_hosts? #{state_history.inspect}" }
687+
688+
# Don't use fallback hosts if the last state change was due to a token error
689+
# if state_history.any?
690+
# last_state_change = state_history.last
691+
# if last_state_change[:reason].respond_to?(:code) && last_state_change[:reason].code
692+
# return false if last_state_change[:reason].code >= 40140 && last_state_change[:reason].code < 40150
693+
# end
694+
# end
695+
696+
# This logic is utterly bizarre. It pays no attention to the error that caused the disconnection.
677697
if client.fallback_hosts && !client.fallback_hosts.empty?
678698
if connecting? && previous_state && !disconnected_from_connected_state?
679699
use_fallback_if_disconnected? || use_fallback_if_suspended?
@@ -690,7 +710,24 @@ def disconnected_from_connected_state?
690710
end
691711

692712
def use_fallback_if_disconnected?
693-
second_reconnect_attempt_for(:disconnected, 1)
713+
unless second_reconnect_attempt_for(:disconnected, 1)
714+
return false
715+
end
716+
717+
last_state_change = state_history.last
718+
logger.debug { "LAWRENCE: last_state_change in disconnected thing: #{last_state_change.inspect} with reason #{last_state_change[:metadata].reason}" }
719+
logger.debug { "LAWRENCE: last_disconnected_reason: #{last_disconnected_reason.inspect}" }
720+
721+
does_error_necessitate_fallback(last_disconnected_reason)
722+
end
723+
724+
def does_error_necessitate_fallback(error)
725+
# RSC15l
726+
if error.respond_to?(:status_code) && error.status_code == 401 && error.respond_to?(:code) && Ably::Exceptions::TOKEN_EXPIRED_CODE.include?(error.code)
727+
return false
728+
end
729+
730+
true
694731
end
695732

696733
def use_fallback_if_suspended?
@@ -700,6 +737,12 @@ def use_fallback_if_suspended?
700737
def second_reconnect_attempt_for(state, first_attempt_count)
701738
previous_state == state && manager.retry_count_for_state(state) >= first_attempt_count
702739
end
740+
741+
def last_disconnected_reason
742+
history_item = state_history.reverse.find do |history_item|
743+
history_item.fetch(:state) == :disconnected
744+
end.fetch(:metadata).reason
745+
end
703746
end
704747
end
705748
end

lib/ably/realtime/connection/connection_manager.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Connection
1212
class ConnectionManager
1313
# Error codes from the server that can potentially be resolved
1414
RESOLVABLE_ERROR_CODES = {
15+
# TODO what is this
1516
token_expired: Ably::Exceptions::TOKEN_EXPIRED_CODE
1617
}
1718
using Ably::Util::AblyExtensions

spec/acceptance/realtime/connection_failures_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,7 @@ def kill_connection_transport_and_prevent_valid_resume
13581358
end)
13591359
end
13601360

1361+
# TODO what's going on in this test?
13611362
it 'triggers a re-authentication and then resumes the connection' do
13621363
# [PENDING] After sandbox env update connection isn't found and a new connection is created. Spec fails
13631364
#
@@ -1367,8 +1368,24 @@ def kill_connection_transport_and_prevent_valid_resume
13671368
connecting_attempts = 0
13681369
connection.on(:connecting) { connecting_attempts += 1 }
13691370

1371+
# My understanding of what's going on here:
1372+
#
1373+
# 1. Connect with a token that expires in 4 seconds
1374+
# 2. Make sure that we don't receive the token DISCONNECTED from Ably, so that RTN15h1 doesn't happen (i.e. we don't try and get a new token yet)
1375+
# 3. Then we wait for Ably to close the transport (actually, we simulate a closing of the transport)
1376+
# - This should take us from CONNECTED to CONNECTING per RTN15a
1377+
# 4. So then we should attempt to resume, with the same expired token
1378+
# 5. This resume should fail with a token error, so per RTN15c5 we need to follow RTN15h, i.e. remain CONNECTING, fetch another token, and reconnect
1379+
# 6. So then we should end up in CONNECTED
1380+
1381+
# So, things I'm seeing in the failing test logs:
1382+
# - the transport-disconnected reconnect (i.e. 4) happens to the primary host
1383+
# - the post-renew reconnect (i.e. 5) happens to a fallback host
1384+
13701385
connection.once(:connected) do
13711386
expect(@auth_requests).to eql(2) # initial + reconnect fails due to expiry & then obtains new token
1387+
# I don't think that this is correct per the spec, there's not meant to be a DISCONNECTED at all, no? Well, that's a separate matter
1388+
# Seems, from looking at logs, that in both 3 and 5 there is a DISCONNECTED where I wouldn't expect one
13721389
expect(connecting_attempts).to eql(2) # reconnect with failed token, then reconnect with successful token
13731390
expect(connection.id).to eql(connection_id)
13741391
stop_reactor

spec/support/debug_failure_helper.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
config.after(:example) do |example|
3131
next if example.metadata[:prevent_log_stubbing]
3232

33-
exception = example.exception
34-
puts "\n#{'-'*34}\n\e[36mVerbose Ably log from test failure\e[0m\n#{'-'*34}\n#{@log_output.join("\n")}\n\n" if exception
33+
puts "\n#{'-'*34}\n\e[36mVerbose Ably log\e[0m\n#{'-'*34}\n#{@log_output.join("\n")}\n\n"
3534
end
3635
end

0 commit comments

Comments
 (0)