public async Task <StatusResponse> Get( [FromServices] ILoadBalancer registry, [FromServices] IHttpClientFactory factory, [FromServices] ILogger <StatusController> logger) { var configHosts = registry.GetConfig(); logger.LogInformation("STATUS request with {0} hosts configured", configHosts.Length); using var client = factory.CreateClient("status"); async Task <string?> GetStatus(Uri statusUri, CancellationToken token) { try { var response = await client.GetAsync(statusUri, HttpCompletionOption.ResponseContentRead, token); if (response.IsSuccessStatusCode) { var responseContent = await response.Content.ReadAsStringAsync(); return(responseContent); } logger.LogError("Error getting /STATUS from {0}: got {1}", statusUri, response.StatusCode); return(null); } catch (Exception e) { logger.LogError("Error getting /STATUS from {0}: {1}", statusUri, e.Message); return(null); } } var cts = new CancellationTokenSource(4000); var responses = await Task.WhenAll( from host in configHosts let statusUri = new Uri(new Uri(host.HostUri), "/status") select GetStatus(statusUri, cts.Token) ); var stats = new StatusResponse(); foreach (var statusPayload in responses.Where(r => !string.IsNullOrEmpty(r))) { var hs = JsonSerializer.Deserialize <StatusResponse>(statusPayload); stats.Merge(hs); } return(stats); }
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())); // } }