private async Task SyncConfig(CancellationToken cancellationToken) { var runningHosts = _balancer.GetConfig().ToDictionary(c => new Uri(c.HostUri), c => c); var newConfig = _configOptions.CurrentValue; var newHosts = newConfig.Hosts.ToDictionary(c => new Uri(c.HostUri), c => c); // TODO optimize alive-ness request // var consideredAlive = _sessionHandler.GetAliveHosts(DateTimeOffset.Now - TimeSpan.FromSeconds(30)); var hostsStatus = await CheckAliveStatus(from h in newConfig.Hosts select new Uri(h.HostUri)); Predicate <Uri> isAlive = uri => hostsStatus.TryGetValue(uri, out var x) && x && newHosts.TryGetValue(uri, out var config) && config.Limit > 0; var toBeRemoved = (from host in runningHosts.Keys where !newHosts.ContainsKey(host) || !isAlive(host) select host).ToArray(); var toBeStarted = (from host in newHosts.Keys where (!runningHosts.ContainsKey(host) || !areConfigsEqual(newHosts[host], runningHosts[host])) && isAlive(host) select host).ToArray(); if (toBeRemoved.Any() || toBeStarted.Any()) { _logger.LogInformation("Detected changes in configuration or availability of the hosts"); } await Task.WhenAll( from host in toBeRemoved select _balancer.DeleteHost(host) ); await Task.WhenAll( from host in toBeStarted select _balancer.AddHost(newHosts[host]) ); // TODO update status monitor queue // if (hostsStatus.Any(status => status.Value == false)) // { // var deadHosts = from h in newConfig.Hosts where !isAlive(h.HostUri) select h.HostUri; // _logger.LogWarning("Hosts not available: {0}", string.Join(", ", deadHosts.ToArray())); // } }