예제 #1
0
        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;
            }
        }