public Task SetState(ConnectionStateBase newState, bool skipAttach = false) { if (Logger.IsDebug) { Logger.Debug($"xx Changing state from {ConnectionState} => {newState.State}. SkipAttach = {skipAttach}."); } _inTransitionToState = newState; return(ExecuteOnManagerThread(async() => { try { lock (_stateSyncLock) { if (State.State == newState.State) { if (Logger.IsDebug) { Logger.Debug($"xx State is already {State.State}. Skipping SetState action."); } return; } //Abort any timers on the old state State.AbortTimer(); if (Logger.IsDebug) { Logger.Debug($"xx {newState.State}: BeforeTransition"); } newState.BeforeTransition(); AttemptsInfo.UpdateAttemptState(newState); Connection.UpdateState(newState); } if (skipAttach == false) { if (Logger.IsDebug) { Logger.Debug($"xx {newState.State}: Attaching state "); } await newState.OnAttachToContext(); } else if (Logger.IsDebug) { Logger.Debug($"xx {newState.State}: Skipping attaching."); } await ProcessQueuedMessages(); } catch (AblyException ex) { Logger.Error("Error attaching to context", ex); lock (_transportQueueLock) _queuedTransportMessages.Clear(); Connection.UpdateState(newState); newState.AbortTimer(); if (newState.State != Realtime.ConnectionState.Failed) { SetState(new ConnectionFailedState(this, ex.ErrorInfo)); } } finally { //Clear the state in transition only if the current state hasn't updated it if (_inTransitionToState == newState) { _inTransitionToState = null; } } })); }
public Task SetState(ConnectionStateBase newState, bool skipAttach = false) { if (Logger.IsDebug) { Logger.Debug( $"xx Changing state from {ConnectionState} => {newState.State}. SkipAttach = {skipAttach}."); } _inTransitionToState = newState; return(ExecuteOnManagerThread(async() => { try { lock (_stateSyncLock) { if (!newState.IsUpdate) { if (State.State == newState.State) { if (Logger.IsDebug) { Logger.Debug($"xx State is already {State.State}. Skipping SetState action."); } return; } AttemptsInfo.UpdateAttemptState(newState); State.AbortTimer(); } if (Logger.IsDebug) { Logger.Debug($"xx {newState.State}: BeforeTransition"); } newState.BeforeTransition(); if (Logger.IsDebug) { Logger.Debug($"xx {newState.State}: BeforeTransition end"); } Connection.UpdateState(newState); } if (skipAttach == false) { if (Logger.IsDebug) { Logger.Debug($"xx {newState.State}: Attaching state "); } await newState.OnAttachToContext(); } else if (Logger.IsDebug) { Logger.Debug($"xx {newState.State}: Skipping attaching."); } await ProcessQueuedMessages(); } catch (AblyException ex) { Logger.Error("Error attaching to context", ex); _queuedTransportMessages = new ConcurrentQueue <ProtocolMessage>(); Connection.UpdateState(newState); newState.AbortTimer(); // RSA4c2 & RSA4d if (newState.State == ConnectionState.Connecting && ex.ErrorInfo.Code == 80019 & !ex.ErrorInfo.IsForbiddenError) { await SetState(new ConnectionDisconnectedState(this, ex.ErrorInfo, Logger)); } else if (newState.State != ConnectionState.Failed) { await SetState(new ConnectionFailedState(this, ex.ErrorInfo, Logger)); } } finally { // Clear the state in transition only if the current state hasn't updated it if (_inTransitionToState == newState) { _inTransitionToState = null; } } })); }