public static IServiceCollection ConfigurarRefit(this IServiceCollection services, PoliciesOptions policies, string urlBase)
        {
            //Definindo policies de Retry e timeout
            AsyncRetryPolicy <HttpResponseMessage> retryPolicy = HttpPolicyExtensions
                                                                 .HandleTransientHttpError()
                                                                 .WaitAndRetryAsync(policies.WaitAndRetryConfig.Retry, _ => TimeSpan.FromMilliseconds(policies.WaitAndRetryConfig.Wait));

            AsyncTimeoutPolicy <HttpResponseMessage> timeoutPolicy = Policy
                                                                     .TimeoutAsync <HttpResponseMessage>(TimeSpan.FromMilliseconds(policies.WaitAndRetryConfig.Timeout));

            //Adicionar o client do Refit nas interfaces de serviços
            services.AddRefitClient <IRendaFixaService>()
            .ConfigureHttpClient(c => c.BaseAddress = new Uri(urlBase))
            .AddPolicyHandler(retryPolicy)
            .AddPolicyHandler(timeoutPolicy);
            services.Decorate <IRendaFixaService, RendaFixaService>();

            services.AddRefitClient <IFundosService>()
            .ConfigureHttpClient(c => c.BaseAddress = new Uri(urlBase))
            .AddPolicyHandler(retryPolicy)
            .AddPolicyHandler(timeoutPolicy);
            services.Decorate <IFundosService, FundosService>();

            services.AddRefitClient <ITesouroDiretoService>()
            .ConfigureHttpClient(c => c.BaseAddress = new Uri(urlBase))
            .AddPolicyHandler(retryPolicy)
            .AddPolicyHandler(timeoutPolicy);
            services.Decorate <ITesouroDiretoService, TesouroDiretoService>();

            return(services);
        }
        public WaitRetryDelegateTimeoutService()
        {
            httpClient.BaseAddress = new Uri("https://localhost:44354/");
            httpClient.Timeout     = new TimeSpan(0, 0, 30);
            httpClient.DefaultRequestHeaders.Clear();

            httpWaitAndRetry = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                               .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) / 2));

            // this is not the same as setting timeout for HttpClient
            // if the request does not respond in the given time (ex. 5 seconds), TimeoutRejectedException is thrown
            timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(5, TimeoutStrategy.Pessimistic);

            httpretryPolicyForHttpClienTimeout = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                                                 .Or <HttpRequestException>()
                                                 .RetryAsync(1, onRetry: OnRetry);

            httpWaitAndRetryWithDelegate = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                                           .WaitAndRetryAsync(3, retryAttempt =>
                                                              TimeSpan.FromSeconds(Math.Pow(2, retryAttempt) / 2), onRetry: (httpResponseMessage, retryCount) =>
            {
                // Log
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"Request failed...{httpResponseMessage.Result.StatusCode}");

                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine($"Retrying...");
                Console.ForegroundColor = ConsoleColor.White;
            });

            httpFallbackPolicy = Policy.HandleResult <HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound)
                                 .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
            {
            });
        }
Example #3
0
        public Task <HttpResponseMessage> MakeRetryingCall(
            Func <HttpRequestMessage, CancellationToken, Task <HttpResponseMessage> > asyncHttpCall,
            HttpRequestMessage requestMessage,
            CancellationToken cancellationToken)
        {
            AsyncTimeoutPolicy timeOutPolicy = Policy.TimeoutAsync(
                retryConfiguration.TotalElapsedTimeInSecs,
                TimeoutStrategy.Optimistic,
                onTimeoutAsync: (context, timespan, t1, exception) => throw new OciException(
                    HttpStatusCode.RequestTimeout,
                    "Request has been timed out. Please increase the total elapsed time for this request and retry",
                    "Unknown",
                    exception)
                );

            AsyncRetryPolicy <HttpResponseMessage> retryAndSleepPolicy = Policy
                                                                         .HandleResult <HttpResponseMessage>(r => ShoulRetryOnHttpResponse(r))
                                                                         .WaitAndRetryAsync(
                retryCount: retryConfiguration.MaxAttempts,
                sleepDurationProvider: (retryCount, response, context) => TimeSpan.FromSeconds(retryConfiguration.GetNextDelayInSeconds(retryCount)),
                onRetryAsync: async(response, timespan, retryAttempt, context) =>
            {
                logger.Info($"Retry Attempt: {retryAttempt}");
                await Task.CompletedTask;
            }
                );

            return(timeOutPolicy
                   .WrapAsync(retryAndSleepPolicy)
                   .ExecuteAsync(() => asyncHttpCall.Invoke(requestMessage, cancellationToken)));
        }
        public static AsyncPolicyWrap CreateExecutionPolicyWrapper()
        {
            // Following example causes the policy to return a bad request HttpResponseMessage with a probability of 5% if enabled
            var fault = new CosmosException("Simulated cosmos exception", HttpStatusCode.ServiceUnavailable, -1, "", 0);
            AsyncInjectOutcomePolicy injectOutcomePolicy = CreateChaosFaultPolicy <CosmosException>(fault);
            AsyncTimeoutPolicy       timeoutPolicy       = CreateTimeOutPolicy(5, TimeoutStrategy.Pessimistic);

            return(Policy.WrapAsync(timeoutPolicy, injectOutcomePolicy));
        }
        public static void Build(IPolicyRegistry <string> registry)
        {
            //PolicyRegistry registry = new PolicyRegistry();
            //Basic Retry Policy
            AsyncRetryPolicy <HttpResponseMessage> basicRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(result => !result.IsSuccessStatusCode)
                .RetryAsync(2);

            registry.Add(BasicRetryPolicy, basicRetryPolicy);


            //Wait and Retry Policy
            AsyncRetryPolicy <HttpResponseMessage> waitAndRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(result => !result.IsSuccessStatusCode)
                .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromMilliseconds(100 * retryAttempt), onRetryAsync: WaitAndRetryHandler);

            registry.Add(WaitAndRetryPolicy, waitAndRetryPolicy);


            ////Retry Policy with onRetryAsync Delegate
            AsyncRetryPolicy <HttpResponseMessage> retryWithDelegatePolicy =
                Policy.HandleResult <HttpResponseMessage>(result => !result.IsSuccessStatusCode)
                .RetryAsync(2, onRetryAsync: OnRetry);

            registry.Add(RetryWithDelegatePolicy, retryWithDelegatePolicy);


            ////Retry Policy or HttpRequestException along with onRetryAsync Delegate
            AsyncRetryPolicy <HttpResponseMessage> retryOrExceptionPolicy =
                Policy.HandleResult <HttpResponseMessage>(result => !result.IsSuccessStatusCode)
                .Or <HttpRequestException>()
                .RetryAsync(2, onRetryAsync: OnRetry);

            registry.Add(RetryOrExceptionPolicy, retryOrExceptionPolicy);


            //Fallback Policy
            AsyncFallbackPolicy <HttpResponseMessage> asyncFallbackPolicy =
                Policy.HandleResult <HttpResponseMessage>(result => !result.IsSuccessStatusCode)
                .Or <TimeoutRejectedException>()
                .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent(typeof(int), int.MaxValue, new JsonMediaTypeFormatter())
            }, onFallbackAsync: FallbackAsyncHandler);

            registry.Add(FallbackWithTimedOutExceptionPolicy, asyncFallbackPolicy);


            //TimeoutPolicy
            AsyncTimeoutPolicy <HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(1, onTimeoutAsync: TimeoutAsyncHandler);

            registry.Add(TimeoutPolicy, timeoutPolicy);
        }
Example #6
0
 async Task TimeoutPolicy()
 {
     AsyncTimeoutPolicy timeoutPolicy = Policy.TimeoutAsync(5, TimeoutStrategy.Pessimistic, onTimeoutAsync: (context, timespan, task) =>
     {
         _logger.LogError($"{context.PolicyKey} at {context.OperationKey}: execution timed out after {timespan.TotalSeconds} seconds.");
         _cts.Cancel();
         _cts = new CancellationTokenSource();
         ExecuteAsync(_cts.Token).GetAwaiter();
         return(Task.CompletedTask);
     });
     HttpResponseMessage httpResponse = await timeoutPolicy
                                        .ExecuteAsync(async ct => await _apiClient.SendRequest(_cts.Token), _cts.Token);
 }
Example #7
0
        public async Task <PolicyResult <TOutput> > ExecuteWithTimeoutAsync <TOutput>(Func <CancellationToken, TOutput> func, int timeout, CancellationToken relatedToken)
        {
            CancellationEnforcer <TOutput> cancellationEnforcer = new CancellationEnforcer <TOutput>();

            // need a little bit of extra time to allow the globalTimer to execute first
            AsyncTimeoutPolicy timeoutPolicy = Policy.TimeoutAsync(timeout + 1, TimeoutStrategy.Optimistic);

            PolicyResult <TOutput> policyResult = await timeoutPolicy.ExecuteAndCaptureAsync(
                async ct => await cancellationEnforcer.AskVinnyToKeepWatch(func, ct), relatedToken
                );

            return(policyResult);
        }
Example #8
0
        public static async Task Run()
        {
            AsyncTimeoutPolicy policy = GetPolicy();

            var cancellationToken = new CancellationToken();
            await policy.ExecuteAsync(async (ct) =>
            {
                Console.WriteLine($"Start Execution at {DateTime.UtcNow.ToLongTimeString()}");
                await Task.Delay(10000, ct);
                Console.WriteLine($"Finish Execution at {DateTime.UtcNow.ToLongTimeString()}");
            }, cancellationToken);

            Console.WriteLine("Done");
        }
Example #9
0
        //constructor injection
        public Cats(HttpClient httpClient, IOptions <ConfigSettings> config)
        {
            _httpClient = httpClient;
            _urls       = config.Value;

            //handle re-tries for http failures (can be pushed to start up at time of registeration)
            _httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(msg => msg.StatusCode == System.Net.HttpStatusCode.GatewayTimeout)
                .Or <TimeoutRejectedException>()
                .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

            //set timeout policy
            _timeoutPolicy = Policy.TimeoutAsync(25);
        }
        private static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
        {
            AsyncTimeoutPolicy timeout = Policy.TimeoutAsync(7);

            return(HttpPolicyExtensions
                   // Handle HttpRequestExceptions, 408 and 5xx status codes
                   .HandleTransientHttpError()
                   // Handle 404 not found
                   .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
                   // Handle 401 Unauthorized
                   .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                   // What to do if any of the above erros occur:
                   // Retry 3 times, each time wait 1,2 and 4 seconds before retrying.
                   .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))).WrapAsync(timeout));
        }
Example #11
0
        public AglIdentitySvc(HttpClient httpClient, ILogger <AglIdentitySvc> logger, IOptions <IdentityConfig> config)
        {
            client  = httpClient;
            _logger = logger;
            _urls   = config.Value;

            //set polly retry policies for microservices
            _httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(msg => msg.StatusCode == System.Net.HttpStatusCode.GatewayTimeout)
                .Or <TimeoutRejectedException>()
                .WaitAndRetryAsync(2, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

            //set timeout policy
            _timeoutPolicy = Policy.TimeoutAsync(25);
        }
Example #12
0
        public static IServiceCollection AddHelloClient(this IServiceCollection services)
        {
            // --> Create: Polly policy.
            AsyncRetryPolicy <HttpResponseMessage> retryPolicy = HttpPolicyExtensions
                                                                 .HandleTransientHttpError()
                                                                 .Or <TimeoutRejectedException>() // Thrown by Polly's TimeoutPolicy if the inner call gets timeout.
                                                                 .WaitAndRetryAsync(2, _ => TimeSpan.FromMilliseconds(500));

            AsyncTimeoutPolicy <HttpResponseMessage> timeoutPolicy = Policy
                                                                     .TimeoutAsync <HttpResponseMessage>(TimeSpan.FromMilliseconds(500));

            services.AddHttpClient <IHelloClient, HelloClient>(c => c.BaseAddress = new Uri("http://localhost:5000"))
            .AddPolicyHandler(retryPolicy)
            .AddPolicyHandler(timeoutPolicy);

            return(services);
        }
Example #13
0
        public CatalogController()
        {
            _timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(1, onTimeoutAsync: TimeoutDelegate);

            _httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                .Or <TimeoutRejectedException>()
                .RetryAsync(3, onRetry: HttpRetryPolicyDelegate);

            _httpRequestFallbackPolicy = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                                         .Or <TimeoutRejectedException>()
                                         .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent(_cachedResult.GetType(), _cachedResult, new JsonMediaTypeFormatter())
            }, onFallbackAsync: HttpRequestFallbackPolicyDelegate);

            _policyWrap = Policy.WrapAsync(_httpRequestFallbackPolicy, _httpRetryPolicy, _timeoutPolicy);
        }
Example #14
0
        public CatalogController()
        {
            // throws TimeoutRejectedException if timeout of 1 second is exceeded.
            _httpTimeoutPolicy = Policy.TimeoutAsync(1);

            _httpRetryPolicy = Policy
                               .HandleResult <HttpResponseMessage>(response => !response.IsSuccessStatusCode)
                               .Or <TimeoutRejectedException>()
                               .RetryAsync(3);

            _httpFallbackPolicy = Policy
                                  .HandleResult <HttpResponseMessage>(response => !response.IsSuccessStatusCode)
                                  .Or <TimeoutRejectedException>()
                                  .FallbackAsync(
                new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent(_cachedResult.GetType(), _cachedResult, new JsonMediaTypeFormatter())
            }
                );
        }
Example #15
0
        internal static ICameraBotBuilder AddHttpClient(this ICameraBotBuilder builder)
        {
            using ServiceProvider serviceProvider = builder.Services.BuildServiceProvider(false);
            CameraBotOptions options = serviceProvider.GetRequiredService <IOptions <CameraBotOptions> >().Value;

            AsyncRetryPolicy <HttpResponseMessage> retryPolicy = HttpPolicyExtensions
                                                                 .HandleTransientHttpError()
                                                                 .Or <TimeoutRejectedException>()
                                                                 .RetryAsync(options.RetryCount);

            AsyncTimeoutPolicy <HttpResponseMessage> timeoutPolicy =
                Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromMilliseconds(options.TimeoutMilliseconds));

            builder.Services
            .AddHttpClient <ICameraService, CameraService>()
            .AddPolicyHandler(retryPolicy)
            .AddPolicyHandler(timeoutPolicy);

            return(builder);
        }
Example #16
0
    public CatalogController()
    {
        //simple retry
        // _httpRetryPolicy = Policy
        // .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
        // .RetryAsync(3);

        //simple retry includes timeout
        _httpRetryPolicy = Policy
                           .HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                           .Or <HttpRequestException>()
                           .Or <TimeoutRejectedException>()
                           .RetryAsync(3, onRetry);

        //simpley retry com funcao quando fail pre retry
        // _httpRetryPolicy = Policy
        // .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
        // .RetryAsync(3, (res, retryCounter) =>
        // {
        //     if(res.Result.StatusCode == System.Net.HttpStatusCode.Unauthorized) {
        //         _httpClient = GetHttpClientWithCookie();

        //     }
        // });

        //backoff retry
        //aumenta o delay para o retry por potencia
        // _httpRetryPolicy = Policy
        // .HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
        // .WaitAndRetryAsync(3, retryTime => TimeSpan.FromSeconds(Math.Pow(2, retryTime) / 2));

        //fallback (cached values on req fails)
        _fallbackPolicy = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                          .Or <TimeoutRejectedException>()
                          .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StringContent("99")
        });

        _timeoutPolicy = Policy.TimeoutAsync(2);
    }
Example #17
0
        public PollyQoSProvider(DownstreamReRoute reRoute, IOcelotLoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger <PollyQoSProvider>();

            Enum.TryParse(reRoute.QosOptions.TimeoutStrategy, out TimeoutStrategy strategy);

            _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptions.TimeoutValue), strategy);

            if (reRoute.QosOptions.ExceptionsAllowedBeforeBreaking > 0)
            {
                _circuitBreakerPolicy = Policy
                                        .Handle <HttpRequestException>()
                                        .Or <TimeoutRejectedException>()
                                        .Or <TimeoutException>()
                                        .CircuitBreakerAsync(
                    exceptionsAllowedBeforeBreaking: reRoute.QosOptions.ExceptionsAllowedBeforeBreaking,
                    durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptions.DurationOfBreak),
                    onBreak: (ex, breakDelay) =>
                {
                    _logger.LogError(
                        ".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
                },
                    onReset: () =>
                {
                    _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again.");
                },
                    onHalfOpen: () =>
                {
                    _logger.LogDebug(".Breaker logging: Half-open; next call is a trial.");
                }
                    );
            }
            else
            {
                _circuitBreakerPolicy = null;
            }

            CircuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy);
        }
Example #18
0
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            WaitAndRetryConfig wrc = Configuration.BindTo <WaitAndRetryConfig>();

            // Add: MessageHandler(s) to the DI container.
            services.AddTransient <AuthorizationMessageHandler>();

            // --> Create: Polly policy.
            AsyncRetryPolicy <HttpResponseMessage> retryPolicy = HttpPolicyExtensions
                                                                 .HandleTransientHttpError()
                                                                 .Or <TimeoutRejectedException>() // Thrown by Polly's TimeoutPolicy if the inner call gets timeout.
                                                                 .WaitAndRetryAsync(wrc.Retry, _ => TimeSpan.FromMilliseconds(wrc.Wait));

            AsyncTimeoutPolicy <HttpResponseMessage> timeoutPolicy = Policy
                                                                     .TimeoutAsync <HttpResponseMessage>(TimeSpan.FromMilliseconds(wrc.Timeout));

            // !! Problem: AuthorizationHeaderValueGetter is not called by the library, if you add with AddRefitClient.

            //RefitSettings refitSettings = new RefitSettings
            //{
            //  AuthorizationHeaderValueGetter = () => Task.FromResult("TestToken")
            //};

            // --> Add: RefitClient.
            services.AddRefitClient <IUserClient>()
            .ConfigureHttpClient(c => c.BaseAddress = new Uri("http://localhost:5000"))
            .AddPolicyHandler(retryPolicy)
            .AddPolicyHandler(timeoutPolicy)                        // The order of adding is imporant!
            .AddHttpMessageHandler <AuthorizationMessageHandler>(); // RefitSettings does not work.

            // --> Decorate IUserClient(RefitClient) with UserClient implementation.
            services.Decorate <IUserClient, UserClient>();

            services.AddRefitClient <IJsonPlaceholderClient>()
            .ConfigureHttpClient(c => c.BaseAddress = new Uri("http://jsonplaceholder.typicode.com"));
        }
        public Task <HttpResponseMessage> MakeRetryingCall(
            Func <HttpRequestMessage, CancellationToken, Task <HttpResponseMessage> > asyncHttpCall,
            HttpRequestMessage requestMessage,
            CancellationToken cancellationToken)
        {
            AsyncTimeoutPolicy timeOutPolicy = Policy.TimeoutAsync(
                retryConfiguration.TotalElapsedTimeInSecs,
                TimeoutStrategy.Optimistic,
                onTimeoutAsync: (context, timespan, t1, exception) => throw new OciException(
                    HttpStatusCode.RequestTimeout,
                    "Request has been timed out. Please increase the total elapsed time for this request and retry",
                    "Unknown",
                    exception)
                );

            AsyncRetryPolicy <HttpResponseMessage> retryAndSleepPolicy = Policy
                                                                         .HandleResult <HttpResponseMessage>(r => ShoulRetryOnHttpResponse(r))
                                                                         .WaitAndRetryAsync(
                retryCount: retryConfiguration.MaxAttempts,
                sleepDurationProvider: (retryCount, response, context) => TimeSpan.FromSeconds(retryConfiguration.GetNextDelayInSeconds(retryCount)),
                onRetryAsync: async(response, timespan, retryAttempt, context) =>
            {
                logger.Info($"Retry Attempt: {retryAttempt}");
                await Task.CompletedTask.ConfigureAwait(false);
            }
                );

            return(timeOutPolicy
                   .WrapAsync(retryAndSleepPolicy)
                   .ExecuteAsync(async() =>
            {
                // A new copy of the request message needs to be created because it is disposed each time it is sent, and
                // resending the same request will result in the following error message:
                // "The request message was already sent. Cannot send the same request message multiple times."
                var newRequestMessage = CloneHttpRequestMessage(requestMessage);
                return await asyncHttpCall.Invoke(newRequestMessage, cancellationToken).ConfigureAwait(false);
            }));
        }
Example #20
0
        public CatalogController(IHttpClientFactory clientFactory)
        {
            _httpClientFactory = clientFactory;

            _httpRetryPolicy = Policy.HandleResult <HttpResponseMessage>(result => result.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                               .Or <TimeoutRejectedException>()
                               .RetryAsync(3);

            _httpWaitAndRetryPolicy = Policy.HandleResult <HttpResponseMessage>(result => !result.IsSuccessStatusCode)
                                      .WaitAndRetryAsync(3, sleepDurationProvider: retryCount =>
                                                         TimeSpan.FromSeconds(Math.Pow(2, retryCount) / 2),
                                                         onRetry: (httpResponseMessage, time, context) =>
            {
                if (httpResponseMessage.Result.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    Debug.WriteLine("There was issue with authentication");
                }
                else
                {
                    if (context.Contains("Logging") && context["Logging"].ToString() == "Enabled")
                    {
                        Debug.WriteLine(httpResponseMessage.Result.Content.ReadAsStringAsync().Result);
                    }
                }
            });

            _fallbackPolicy = Policy.HandleResult <HttpResponseMessage>(result => !result.IsSuccessStatusCode)
                              .FallbackAsync(new HttpResponseMessage(System.Net.HttpStatusCode.OK)
            {
                Content = new StringContent("Cached Default Result")
            });

            _timeoutPolicy = Policy.TimeoutAsync(seconds: 1);

            _policyWrap = _fallbackPolicy.WrapAsync(_httpWaitAndRetryPolicy.WrapAsync(_timeoutPolicy));
        }
        /// <summary>
        /// Generates the circuit breaker policy for a service.
        /// </summary>
        /// <param name="serviceInfo">The service to generate the circuit breaker policy for</param>
        /// <returns>The circuit policy</returns>
        protected AsyncPolicyWrap <ServiceResponse> GetCircuitBreakerPolicy(CalledServiceInfo serviceInfo)
        {
            return(CircuitBreakerPolicies.GetOrAdd(serviceInfo.CacheKey, _ =>
            {
                AsyncTimeoutPolicy timeoutPolicy = Policy
                                                   .TimeoutAsync(
                    serviceInfo.Timeout,
                    TimeoutStrategy.Pessimistic
                    );

                AsyncCircuitBreakerPolicy <ServiceResponse> circuitBreakerPolicy = Policy <ServiceResponse>
                                                                                   .Handle <TimeoutRejectedException>()
                                                                                   .OrResult(resultPredicate: serviceResponse => serviceResponse.Status == ServiceResponseStatus.Error)
                                                                                   .CircuitBreakerAsync(
                    handledEventsAllowedBeforeBreaking: serviceInfo.CircuitBreakerInfo.ExceptionCount,
                    durationOfBreak: serviceInfo.CircuitBreakerInfo.BreakDuration,
                    onBreak: (__, ___) =>
                {
                    Log.Warning("Service ({ServiceName}) has reached its threshold for the circuit breaker and the circuit has been opened", serviceInfo.Name);
                },
                    onReset: () =>
                {
                    Log.Warning("Service ({ServiceName}) has been determined to be back up, circuit closed again", serviceInfo.Name);
                }
                    );

                AsyncPolicyWrap <ServiceResponse> circuitBreakerWrappingTimeout = circuitBreakerPolicy
                                                                                  .WrapAsync(timeoutPolicy);

                AsyncFallbackPolicy <ServiceResponse> timeoutFallbackPolicy = Policy <ServiceResponse>
                                                                              .Handle <TimeoutRejectedException>()
                                                                              .FallbackAsync(
                    cancellationToken =>
                {
                    return Task.FromResult(new ServiceResponse
                    {
                        Status = ServiceResponseStatus.Timeout,
                        ServiceId = serviceInfo.Id
                    });
                });
                AsyncPolicyWrap <ServiceResponse> timeoutFallbackPolicyWrappingCircuitBreaker = timeoutFallbackPolicy
                                                                                                .WrapAsync(circuitBreakerWrappingTimeout);

                AsyncFallbackPolicy <ServiceResponse> exceptionFallbackPolicy = Policy <ServiceResponse>
                                                                                .Handle <Exception>()
                                                                                .FallbackAsync(
                    cancellationToken =>
                {
                    return Task.FromResult(new ServiceResponse
                    {
                        Status = ServiceResponseStatus.Error,
                        ServiceId = serviceInfo.Id
                    });
                });
                AsyncPolicyWrap <ServiceResponse> exceptionFallbackPolicyWrappingTimeoutFallback = exceptionFallbackPolicy
                                                                                                   .WrapAsync(timeoutFallbackPolicyWrappingCircuitBreaker);

                AsyncPolicyWrap <ServiceResponse> policy = exceptionFallbackPolicyWrappingTimeoutFallback;

                return policy;
            }));
        }
        public async Task <IEnumerable <Result> > GetHeroes(string limite)
        {
            //if(_client == null)
            //{
            //_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            //_client.BaseAddress
            //}


            //Posso melhorar o tratamento do handleResult
            //https://dev.to/rickystam/net-core-use-httpclientfactory-and-polly-to-build-rock-solid-services-2edh

            //referencia
            //https://www.davidbritch.com/2017/07/transient-fault-handling-in.html
            _httpRetryPolicy = Policy.HandleResult <HttpResponseMessage>(r => httpStatusCodesToRetry.Contains(r.StatusCode))
                               .Or <TimeoutRejectedException>()
                               .Or <Exception>()
                               //.OrResult<HttpResponseMessage>(r => httpStatusCodesToRetry.Contains(r.StatusCode))
                               //.Handle<HttpRequestException>(ex => !ex.Message.ToLower().Contains("404"))
                               .WaitAndRetryAsync
                               (
                //Quantidade de tentaivas
                retryCount: 3,

                //duração entre as tentativas
                sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),

                //O que será executado se der erro
                onRetry: async(response, time, retryCount, context) =>
            {
                if (response.Exception != null)
                {
                    Console.WriteLine($"Ocorreu um erro ao baixar os dados: {response.Exception.Message}, Tentando novamente em {time}, tentativa número: {retryCount}");
                }
                else
                {
                    var rawResponse = await response.Result.Content.ReadAsStringAsync();
                    var json        = JsonConvert.DeserializeAnonymousType(rawResponse, new { code = "", status = "" });
                    Console.WriteLine($"Ocorreu um erro ao baixar os dados: {json.status}, Tentando novamente em {time}, tentativa número: {retryCount}");
                }
            }
                               );

            _timeoutPolicy = Policy.TimeoutAsync(5, TimeoutStrategy.Pessimistic);
            try
            {
                //.ExecuteAsync(async () =>
                //{
                //   Console.WriteLine($"Obtendo Herois...");
                //    var response = await client.GetAsync(GetUrl(limite));
                //    var rawResponse = await response.Content.ReadAsStringAsync();

                //Problemas para retornar um await direito, a melhor opção por enquantp é deixar finalizar o metodo e retornar o objeto depois
                //heroes = JsonConvert.DeserializeObject<Hero>(rawResponse);
                //});


                //Referencia
                //https://nodogmablog.bryanhogan.net/2017/12/using-the-polly-timeout-when-making-a-http-request/
                HttpResponseMessage response = await
                                               _httpRetryPolicy.ExecuteAsync(() =>
                                                                             _timeoutPolicy.ExecuteAsync(async c =>
                                                                                                         await _client.GetAsync(GetUrl(limite), c), CancellationToken.None));

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    var newtonSoft = string.IsNullOrEmpty(await response.Content.ReadAsStringAsync()) ? JsonConvert.DeserializeObject <Hero>(await response.Content.ReadAsStringAsync()) : new Hero();
                    return(new List <Result>().DefaultIfEmpty());
                }
                else
                {
                    //Teste Jil
                    //Stopwatch TimerJill = new Stopwatch();
                    //TimerJill.Start();
                    //var employeeDeserialized = JSON.Deserialize<Hero>(await response.Content.ReadAsStringAsync(), new Options(dateFormat: DateTimeFormat.MicrosoftStyleMillisecondsSinceUnixEpoch));
                    //TimerJill.Stop();
                    //var tempoDecorridoJil = TimerJill.Elapsed.TotalSeconds;
                    var contractResolver = new CustomContractResolver();

                    //Teste using newtonsof
                    Stopwatch TimerNewton = new Stopwatch();
                    TimerNewton.Start();
                    //forma correta  de utilizar, sem jogar atribuir para uma string antes de realizar a deserialização.
                    var newtonSoft = JsonConvert.DeserializeObject <Hero>(await response.Content.ReadAsStringAsync(), new JsonSerializerSettings {
                        ContractResolver = contractResolver
                    });
                    TimerNewton.Stop();
                    var tempoDecorridoNewton = TimerNewton.Elapsed.TotalSeconds;


                    Stopwatch TimerUsing = new Stopwatch();
                    TimerUsing.Start();
                    Hero hero;
                    //Referencia: http://jonathanpeppers.com/Blog/improving-http-performance-in-xamarin-applications
                    using (var stream = await response.Content.ReadAsStreamAsync())
                        //Referencia minBuffer https://stackoverflow.com/questions/56461022/benchmarking-newtonsoft-json-deserialization-from-stream-and-from-string
                        using (var reader = new StreamReader(stream, Encoding.UTF8, true, 128))
                            using (var jsonTextReader = new JsonTextReader(reader))
                            {
                                hero = _serializer.Deserialize <Hero>(jsonTextReader);
                            }
                    TimerUsing.Stop();
                    var tempoDecorridoUsing = TimerUsing.Elapsed.TotalSeconds;



                    string json = await response.Content.ReadAsStringAsync();

                    //Referencia
                    //https://stackoverflow.com/questions/8707755/how-to-know-the-size-of-the-string-in-bytes
                    var howManyBytes = json.Length * sizeof(Char);

                    return(newtonSoft.data.results.EmptyIfNull());
                }



                /*
                 *
                 *
                 *
                 *
                 *  await Policy
                 *      //Se for um erro diferente de 404 ira executar a politica de retry
                 *      //podemos utilizar grupo de statusCode
                 *      //o ideal é trabalhar em cima dos erros de internet, e continuar tratando o resto pelo statusCode
                 *
                 *      //.Handle<TimeoutException>()
                 *      .Handle<HttpRequestException>(ex => !ex.Message.ToLower().Contains("404"))
                 *      .Or<HttpRequestException>()
                 *      //.OrResult<HttpResponseMessage>(r => httpStatusCodesToRetry.Contains(r.StatusCode))
                 *      //.Handle<HttpRequestException>(ex => !ex.Message.ToLower().Contains("404"))
                 *
                 *      .WaitAndRetryAsync
                 *      (
                 *          //Quantidade de tentaivas
                 *          retryCount: 3,
                 *
                 *          //duração entre as tentativas
                 *          sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                 *
                 *          //O que será executado se der erro
                 *          onRetry: (ex, time) =>
                 *          {
                 *              lock (_MessageLock)
                 *              {
                 *                  Console.BackgroundColor = ConsoleColor.Red;
                 *                  Console.WriteLine($"Ocorreu um erro ao baixar os dados: {ex.Message}, tentando novamente em...{time}");
                 *                  Console.ResetColor();
                 *              }
                 *          }
                 *      )
                 *      .ExecuteAsync(async () =>
                 *      {
                 *          var response = await client.GetAsync(GetUrl(limite));
                 *          var rawResponse = await response.Content.ReadAsStringAsync();
                 *
                 *          //Problemas para retornar um await direito, a melhor opção por enquantp é deixar finalizar o metodo e retornar o objeto depois
                 *          heroes = JsonConvert.DeserializeObject<Hero>(rawResponse);
                 *      });
                 *
                 */
                /*
                 *  var response = await client.GetAsync(GetUrl(limite));
                 *
                 *  if (response.StatusCode != System.Net.HttpStatusCode.OK)
                 *  {
                 *      throw new Exception(response.Content.ReadAsStringAsync().Result);
                 *  }
                 *  var rawResponse = await response.Content.ReadAsStringAsync();
                 *  return JsonConvert.DeserializeObject<Hero>(rawResponse);
                 *
                 */
                //return heroes;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }