예제 #1
0
        protected async Task <IDictionary <string, object> > RunReconnect(
            IDictionary <string, object> stepParameters,
            IDictionary <string, object> pluginParameters)
        {
            try
            {
                // Get parameters
                stepParameters.TryGetTypedValue(SignalRConstants.HubUrls, out string urls, Convert.ToString);
                stepParameters.TryGetTypedValue(SignalRConstants.HubProtocol, out string protocol, Convert.ToString);
                stepParameters.TryGetTypedValue(SignalRConstants.TransportType, out string transportType, Convert.ToString);
                stepParameters.TryGetTypedValue(SignalRConstants.Type, out string type, Convert.ToString);
                stepParameters.TryGetTypedValue(SignalRConstants.ConcurrentConnection, out int concurrentConnection, Convert.ToInt32);

                var clientType = SignalREnums.ClientType.AspNetCore;
                if (pluginParameters.TryGetValue($"{SignalRConstants.ConnectionType}.{type}", out _))
                {
                    pluginParameters.TryGetTypedValue($"{SignalRConstants.ConnectionType}.{type}",
                                                      out var connectionType, Convert.ToString);
                    if (Enum.TryParse(connectionType, out SignalREnums.ClientType ct))
                    {
                        clientType = ct;
                    }
                }

                if (SignalRUtils.isUsingInternalApp(stepParameters) && clientType == ClientType.AspNetCore)
                {
                    // rewrite the URL to be localhost
                    stepParameters[SignalRConstants.HubUrls] = SignalRConstants.LocalhostUrl;
                    urls = SignalRConstants.LocalhostUrl;
                }
                // Get context
                pluginParameters.TryGetTypedValue($"{SignalRConstants.ConnectionIndex}.{type}",
                                                  out List <int> connectionIndex, (obj) => (List <int>)obj);
                pluginParameters.TryGetTypedValue($"{SignalRConstants.ConnectionStore}.{type}",
                                                  out IList <IHubConnectionAdapter> connections, (obj) => (IList <IHubConnectionAdapter>)obj);
                pluginParameters.TryGetTypedValue($"{SignalRConstants.RegisteredCallbacks}.{type}",
                                                  out var registeredCallbacks, obj => (IList <Action <IList <IHubConnectionAdapter>, StatisticsCollector> >)obj);
                pluginParameters.TryGetTypedValue($"{SignalRConstants.StatisticsStore}.{type}",
                                                  out StatisticsCollector statisticsCollector, obj => (StatisticsCollector)obj);

                SignalRUtils.DumpConnectionInternalStat(connections);
                // Re-create broken connections in their original index position
                var newConnections = await RecreateBrokenConnections(
                    connections, connectionIndex, urls,
                    transportType, protocol,
                    SignalRConstants.ConnectionCloseTimeout,
                    clientType);

                if (newConnections.Count == 0)
                {
                    // skip reconnect because of no drop
                    Log.Information("Skip reconnect");
                    return(null);
                }
                Log.Information($"Start {newConnections.Count} reconnections");
                // Re-setCallbacks
                foreach (var registerCallback in registeredCallbacks)
                {
                    registerCallback(newConnections, statisticsCollector);
                }
                // It must use original connections instead of 'newConnections' here
                // because the 'connectionSuccessFlag' is for original connections
                await BatchConnect(
                    stepParameters,
                    pluginParameters,
                    connections,
                    concurrentConnection);

                Log.Information($"Finish {newConnections.Count} reconnections");
                var recoverred = (from i in Enumerable.Range(0, newConnections.Count)
                                  where newConnections[i].GetStat() == SignalREnums.ConnectionInternalStat.Active
                                  select newConnections[i]).ToList();
                statisticsCollector.UpdateReconnect(recoverred.Count);
                SignalRUtils.DumpConnectionInternalStat(connections);
                return(null);
            }
            catch (Exception ex)
            {
                var message = $"Fail to reconnect: {ex}";
                Log.Error(message);
                throw;
            }
        }