public IpcClientTcpServerRouterFactory(string ipcClient, string tcpServer, int runtimeTimeoutMs, TcpServerRouterFactory.CreateInstanceDelegate factory, ILogger logger)
 {
     _logger = logger;
     _ipcClientRouterFactory = new IpcClientRouterFactory(ipcClient, logger);
     _tcpServerRouterFactory = factory(tcpServer, runtimeTimeoutMs, logger);
 }
 public IpcClientTcpServerRouterFactory(string ipcClient, string tcpServer, int runtimeTimeoutMs, ILogger logger)
 {
     _logger = logger;
     _ipcClientRouterFactory = new IpcClientRouterFactory(ipcClient, logger);
     _tcpServerRouterFactory = new TcpServerRouterFactory(tcpServer, runtimeTimeoutMs, logger);
 }
        async static Task <int> runRouter(CancellationToken token, TcpServerRouterFactory routerFactory, Callbacks callbacks)
        {
            List <Task>   runningTasks   = new List <Task>();
            List <Router> runningRouters = new List <Router>();

            try
            {
                routerFactory.Start();
                callbacks?.OnRouterStarted(routerFactory.TcpServerAddress);

                while (!token.IsCancellationRequested)
                {
                    Task <Router> routerTask = null;
                    Router        router     = null;

                    try
                    {
                        routerTask = routerFactory.CreateRouterAsync(token);

                        do
                        {
                            // Search list and clean up dead router instances before continue waiting on new instances.
                            runningRouters.RemoveAll(IsRouterDead);

                            runningTasks.Clear();
                            foreach (var runningRouter in runningRouters)
                            {
                                runningTasks.Add(runningRouter.RouterTaskCompleted.Task);
                            }
                            runningTasks.Add(routerTask);
                        }while (await Task.WhenAny(runningTasks.ToArray()).ConfigureAwait(false) != routerTask);

                        if (routerTask.IsFaulted || routerTask.IsCanceled)
                        {
                            //Throw original exception.
                            routerTask.GetAwaiter().GetResult();
                        }

                        if (routerTask.IsCompleted)
                        {
                            router = routerTask.Result;
                            router.Start();

                            // Add to list of running router instances.
                            runningRouters.Add(router);
                            router = null;
                        }

                        routerTask.Dispose();
                        routerTask = null;
                    }
                    catch (Exception ex)
                    {
                        router?.Dispose();
                        router = null;

                        routerTask?.Dispose();
                        routerTask = null;

                        // Timing out on accepting new streams could mean that either the frontend holds an open connection
                        // alive (but currently not using it), or we have a dead backend. If there are no running
                        // routers we assume a dead backend. Reset current backend endpoint and see if we get
                        // reconnect using same or different runtime instance.
                        if (ex is BackendStreamTimeoutException && runningRouters.Count == 0)
                        {
                            routerFactory.Logger.LogDebug("No backend stream available before timeout.");
                            routerFactory.Reset();
                        }

                        // Timing out on accepting a new runtime connection means there is no runtime alive.
                        // Shutdown router to prevent instances to outlive runtime process (if auto shutdown is enabled).
                        if (ex is RuntimeTimeoutException)
                        {
                            routerFactory.Logger.LogInformation("No runtime connected before timeout.");
                            routerFactory.Logger.LogInformation("Starting automatic shutdown.");
                            throw;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                routerFactory.Logger.LogInformation($"Shutting down due to error: {ex.Message}");
            }
            finally
            {
                if (token.IsCancellationRequested)
                {
                    routerFactory.Logger.LogInformation("Shutting down due to cancelation request.");
                }

                runningRouters.RemoveAll(IsRouterDead);
                runningRouters.Clear();

                await routerFactory?.Stop();

                callbacks?.OnRouterStopped();

                routerFactory.Logger.LogInformation("Router stopped.");
            }
            return(0);
        }