public TimeSpan?GetNextRetryDelay(RetryContext context) { if (context.PreviousRetryCount >= this.backoffTimes.Length) { return(null); } return(this.backoffTimes[context.PreviousRetryCount]); }
private void SetState(ConnectionStates state, string errorReason = null, bool allowReconnect = true) { if (string.IsNullOrEmpty(errorReason)) { HTTPManager.Logger.Information("HubConnection", string.Format("SetState - from State: '{0}' to State: '{1}', allowReconnect: {2}", this.State, state, allowReconnect)); } else { HTTPManager.Logger.Information("HubConnection", string.Format("SetState - from State: '{0}' to State: '{1}', errorReason: '{2}', allowReconnect: {3}", this.State, state, errorReason, allowReconnect)); } if (this.State == state) { return; } var previousState = this.State; this.State = state; switch (state) { case ConnectionStates.Initial: case ConnectionStates.Authenticating: case ConnectionStates.Negotiating: case ConnectionStates.CloseInitiated: break; case ConnectionStates.Reconnecting: HTTPManager.Heartbeats.Subscribe(this); break; case ConnectionStates.Connected: // If reconnectStartTime isn't its default value we reconnected if (this.reconnectStartTime != DateTime.MinValue) { try { if (this.OnReconnected != null) { this.OnReconnected(this); } } catch (Exception ex) { HTTPManager.Logger.Exception("HubConnection", "OnReconnected", ex); } } else { try { if (this.OnConnected != null) { this.OnConnected(this); } } catch (Exception ex) { HTTPManager.Logger.Exception("HubConnection", "Exception in OnConnected user code!", ex); } } HTTPManager.Heartbeats.Subscribe(this); this.lastMessageSent = DateTime.UtcNow; // Clean up reconnect related fields this.currentContext = new RetryContext(); this.reconnectStartTime = DateTime.MinValue; this.reconnectAt = DateTime.MinValue; break; case ConnectionStates.Closed: // No errorReason? It's an expected closure. if (errorReason == null) { if (this.OnClosed != null) { try { this.OnClosed(this); } catch (Exception ex) { HTTPManager.Logger.Exception("HubConnection", "Exception in OnClosed user code!", ex); } } } else { // If possible, try to reconnect if (allowReconnect && this.ReconnectPolicy != null && (previousState == ConnectionStates.Connected || this.reconnectStartTime != DateTime.MinValue)) { // It's the first attempt after a successful connection if (this.reconnectStartTime == DateTime.MinValue) { this.reconnectStartTime = DateTime.UtcNow; try { if (this.OnReconnecting != null) { this.OnReconnecting(this, errorReason); } } catch (Exception ex) { HTTPManager.Logger.Exception("HubConnection", "SetState - ConnectionStates.Reconnecting", ex); } } RetryContext context = new RetryContext { ElapsedTime = DateTime.UtcNow - this.reconnectStartTime, PreviousRetryCount = this.currentContext.PreviousRetryCount, RetryReason = errorReason }; TimeSpan?nextAttempt = null; try { nextAttempt = this.ReconnectPolicy.GetNextRetryDelay(context); } catch (Exception ex) { HTTPManager.Logger.Exception("HubConnection", "ReconnectPolicy.GetNextRetryDelay", ex); } // No more reconnect attempt, we are closing if (nextAttempt == null) { HTTPManager.Logger.Warning("HubConnecction", "No more reconnect attempt!"); // Clean up everything this.currentContext = new RetryContext(); this.reconnectStartTime = DateTime.MinValue; this.reconnectAt = DateTime.MinValue; } else { HTTPManager.Logger.Information("HubConnecction", "Next reconnect attempt after " + nextAttempt.Value.ToString()); this.currentContext = context; this.currentContext.PreviousRetryCount += 1; this.reconnectAt = DateTime.UtcNow + nextAttempt.Value; this.SetState(ConnectionStates.Reconnecting); return; } } if (this.OnError != null) { try { this.OnError(this, errorReason); } catch (Exception ex) { HTTPManager.Logger.Exception("HubConnection", "Exception in OnError user code!", ex); } } } HTTPManager.Heartbeats.Unsubscribe(this); break; } }