public async Task <AblyResponse> Execute(AblyRequest request) { var fallbackHosts = Defaults.FallbackHosts.ToList(); if (CustomHost.IsNotEmpty()) { //The custom host is a fallback host currently in use by the Realtime client. //We need to remove it from the fallback hosts fallbackHosts.Remove(CustomHost); } var random = new Random(); int currentTry = 0; var startTime = Config.Now(); var numberOfRetries = Options.HttpMaxRetryCount; var host = CustomHost.IsNotEmpty() ? CustomHost : Options.Host; while (currentTry < numberOfRetries) { var requestTime = Config.Now(); if ((requestTime - startTime).TotalSeconds >= Options.HttpMaxRetryDuration.TotalSeconds) { Logger.Error("Cumulative retry timeout of {0}s was exceeded", Config.CommulativeFailedRequestTimeOutInSeconds); throw new AblyException( new ErrorInfo(string.Format("Commulative retry timeout of {0}s was exceeded.", Config.CommulativeFailedRequestTimeOutInSeconds), 500, null)); } Logger.Debug("Executing request: " + request.Url + (currentTry > 0 ? $"try {currentTry}" : "")); try { var message = GetRequestMessage(request, host); await LogMessage(message); var response = await Client.SendAsync(message, HttpCompletionOption.ResponseContentRead); var ablyResponse = await GetAblyResponse(response); LogResponse(ablyResponse, request.Url); if (response.IsSuccessStatusCode) { return(ablyResponse); } if (IsRetryableResponse(response) && Options.IsDefaultHost) { Logger.Warning("Failed response. Retrying. Returned response with status code: " + response.StatusCode); if (TryGetNextRandomHost(fallbackHosts, random, out host)) { Logger.Debug("Retrying using host {0}", host); currentTry++; continue; } } throw AblyException.FromResponse(ablyResponse); } catch (HttpRequestException ex) when(IsRetryableError(ex) && Options.IsDefaultHost) { Logger.Warning("Error making a connection to Ably servers. Retrying", ex); if (TryGetNextRandomHost(fallbackHosts, random, out host)) { Logger.Debug("Retrying using host {0}", host); currentTry++; continue; } throw; //_host = hosts[currentTry - 1]; } catch (TaskCanceledException ex) when(IsRetryableError(ex) && Options.IsDefaultHost) { Logger.Warning("Error making a connection to Ably servers. Retrying", ex); if (TryGetNextRandomHost(fallbackHosts, random, out host)) { Logger.Debug("Retrying using host {0}", host); currentTry++; continue; } throw; } catch (HttpRequestException ex) { throw new AblyException(new ErrorInfo("Error executing request", 500), ex); } catch (TaskCanceledException ex) { throw new AblyException(new ErrorInfo("Error executing request", 500), ex); } } throw new AblyException(new ErrorInfo("Error exectuting request", 500)); }
public async Task <AblyResponse> Execute(AblyRequest request) { var fallbackHosts = Options.FallbackHosts.ToList(); if (CustomHost.IsNotEmpty()) { // The custom host is a fallback host currently in use by the Realtime client. // We need to remove it from the fallback hosts fallbackHosts.Remove(CustomHost); } var random = new Random(); int currentTry = 0; var startTime = Now(); var numberOfRetries = Options.HttpMaxRetryCount; var host = CustomHost.IsNotEmpty() ? CustomHost : Options.Host; while (currentTry < numberOfRetries) { DateTimeOffset requestTime = Now(); if ((requestTime - startTime).TotalSeconds >= Options.HttpMaxRetryDuration.TotalSeconds) { Logger.Error("Cumulative retry timeout of {0}s was exceeded", Config.CommulativeFailedRequestTimeOutInSeconds); throw new AblyException( new ErrorInfo($"Commulative retry timeout of {Config.CommulativeFailedRequestTimeOutInSeconds}s was exceeded.", 50000, null)); } Logger.Debug("Executing request: " + request.Url + (currentTry > 0 ? $"try {currentTry}" : string.Empty)); try { var message = GetRequestMessage(request, host); await LogMessage(message); var response = await SendAsync(message).ConfigureAwait(false); var ablyResponse = await GetAblyResponse(response); LogResponse(ablyResponse, request.Url); if (response.IsSuccessStatusCode) { return(ablyResponse); } if (IsRetryableResponse(response) && (Options.IsDefaultHost || Options.FallbackHostsUseDefault)) { Logger.Warning("Failed response. Retrying. Returned response with status code: " + response.StatusCode); if (TryGetNextRandomHost(fallbackHosts, random, out host)) { Logger.Debug("Retrying using host {0}", host); currentTry++; continue; } } if (request.NoExceptionOnHttpError) { return(ablyResponse); } try { response.EnsureSuccessStatusCode(); } catch (HttpRequestException ex) { throw new AblyException(ErrorInfo.Parse(ablyResponse), ex); } throw AblyException.FromResponse(ablyResponse); } catch (HttpRequestException ex) when(IsRetryableError(ex) && (Options.IsDefaultHost || Options.FallbackHostsUseDefault)) { Logger.Warning("Error making a connection to Ably servers. Retrying", ex); if (TryGetNextRandomHost(fallbackHosts, random, out host)) { Logger.Debug("Retrying using host {0}", host); currentTry++; continue; } throw; } catch (TaskCanceledException ex) when(IsRetryableError(ex) && (Options.IsDefaultHost || Options.FallbackHostsUseDefault)) { Logger.Warning("Error making a connection to Ably servers. Retrying", ex); if (TryGetNextRandomHost(fallbackHosts, random, out host)) { Logger.Debug("Retrying using host {0}", host); currentTry++; continue; } throw; } catch (HttpRequestException ex) { StringBuilder reason = new StringBuilder(ex.Message); var innerEx = ex.InnerException; while (innerEx != null) { reason.Append(" " + innerEx.Message); innerEx = innerEx.InnerException; } throw new AblyException(new ErrorInfo(reason.ToString(), 50000), ex); } catch (TaskCanceledException ex) { // if the cancellation was not requested then this is timeout. if (ex.CancellationToken.IsCancellationRequested == false) { throw new AblyException(new ErrorInfo("Error executing request. Request timed out.", 50000), ex); } else { throw new AblyException(new ErrorInfo("Error executing request", 50000), ex); } } } throw new AblyException(new ErrorInfo("Error exectuting request", 50000)); }