private CircuitBreaker MakeCircuitBreaker(IAdaptToBank bankAdapter, Payment payment) { var breaker = Policy .Handle <TaskCanceledException>() .Or <FailedConnectionToBankException>() .CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: 3, durationOfBreak: TimeSpan.FromMilliseconds(40), onBreak: (exception, timespan, context) => { // When circuit breaker opens, buffer failed `PayingAttempt` Buffer(bankAdapter, payment); }, onReset: context => { #pragma warning disable 4014 // Fire and forget (Polly OnReset does not provide awaitable signature) ProcessBufferedPaymentRequest(); #pragma warning restore 4014 }); AsyncPolicyWrap policy = Policy.Handle <TaskCanceledException>() .Or <FailedConnectionToBankException>() .WaitAndRetryAsync(3, retry => TimeSpan.FromMilliseconds(Math.Pow(2, retry))) .WrapAsync(breaker); return(new CircuitBreaker(breaker, policy)); }
public CachedPersistedStoreCacheHandle( PersistedStoreCachingOptions options, ILogger <CachedPersistedStoreCacheHandle> logger) { this.options = options; cache = Utilities.CreateCache(options); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); var circuitBreaker = Utilities .GetCircuitBreakerPolicy( options, logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug), logger, $"PersistedGrantStoreCache is open circuited.\n " + $"Duration: {options.DurationOfBreakInSeconds}", $"PersistedGrantStoreCache circuit breaker is reset", $"PersistedGrantStoreCache circuit breaker is half-open"); getPersistedGrantPolicy = GetFallBackPolicy <PersistedGrant>(circuitBreaker); getPersistedGrantDictionaryPolicy = GetFallBackPolicy <Dictionary <string, PersistedGrant> >(circuitBreaker); setFallBackPolicy = SetFallBackPolicy(circuitBreaker); }
public PollyRetryBreakerHandler(IHttpContextAccessor contextAccessor) { // Get the values for polly var pollyOptions = GetPollyOptionsForContext(contextAccessor.HttpContext); _circuitBreakerPolicy = CreatePollyPolicy(pollyOptions); }
public static AsyncPolicy GenerateRedisPolicy(params IAsyncPolicy[] chainedPolicies) { AsyncPolicy redisServerExceptionRetry = Policy.Handle <RedisServerException>() .WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(15) }); AsyncPolicy circuitBreakerRedisServerException = Policy.Handle <RedisServerException>().CircuitBreakerAsync(1000, TimeSpan.FromMinutes(1)); AsyncPolicy connectionExceptionRetry = Policy.Handle <RedisConnectionException>() .WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15) }); AsyncPolicy connectionExceptionCircuitBreaker = Policy.Handle <RedisConnectionException>().CircuitBreakerAsync(250, TimeSpan.FromMinutes(1)); List <IAsyncPolicy> policies = new List <IAsyncPolicy>(8) { redisServerExceptionRetry, connectionExceptionRetry, circuitBreakerRedisServerException, connectionExceptionCircuitBreaker }; if (!chainedPolicies.IsNullOrEmpty()) { policies.AddRange(chainedPolicies); } AsyncPolicyWrap policyWrap = Policy.WrapAsync(policies.ToArray()); return(policyWrap); }
public override async Task <TReturn> HandleExceptionAsync <TReturn>(Func <CancellationToken, Task <TReturn> > func, CancellationToken funcCancellationToken = default, Func <CancellationToken, Task> onExceptionCompensatingHandler = null, CancellationToken onExceptionCompensatingHandlerCancellationToken = default) { Task <TReturn> returnValue = default; try { var returnValueFromFunc = await func(funcCancellationToken); if (returnValueFromFunc is Task <TReturn> ) { returnValue = returnValueFromFunc as Task <TReturn>; } else { returnValue = Task.FromResult(returnValueFromFunc); } } catch (Exception ex) { returnValue = await ExceptionHandlingUtility.WrapFuncWithExceptionHandling(async() => { if (CheckIfExceptionsNeedsToBePollyHandled(ex)) { AsyncPolicyWrap policyWrap = GetPolicyWrapWithProperFallbackActionSetForFallbackPoliciesAsync(ex, onExceptionCompensatingHandler); return(await policyWrap.ExecuteAsync(func, funcCancellationToken) as Task <TReturn>); } return(default(Task <TReturn>)); }, _logger); await HandleExceptionWithThrowCondition(ex, onExceptionCompensatingHandler, onExceptionCompensatingHandlerCancellationToken); } return(await returnValue); }
public void Should_retry_until_threshold_is_reached() { AsyncCircuitBreakerPolicy breaker = Policy .Handle <Exception>() .CircuitBreakerAsync(3, TimeSpan.FromMilliseconds(1000), OnBreak, OnReset); AsyncPolicyWrap retryPolicy = Policy.Handle <Exception>().RetryAsync(3) .WrapAsync(breaker); //var policy = Policy // .Handle<TaskCanceledException>() // .Or<FailedConnectionToBankException>() // .FallbackAsync(cancel => ReturnWillHandleLater(payment.GatewayPaymentId, payment.RequestId)) // .WrapAsync(breaker); int count = 0; retryPolicy.ExecuteAsync(async() => { Console.WriteLine(count++); await Task.FromException(new Exception()); }); }
public static AsyncPolicy GenerateSearchPolicy(IAsyncPolicy[] chainedPolicies = null) { AsyncPolicy cloudExceptionRetry = Policy.Handle <CloudException>() .WaitAndRetryAsync(new[] { TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(5) }); AsyncPolicy indexBatchExceptionRetry = Policy.Handle <IndexBatchException>() .WaitAndRetryAsync(new[] { TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5) }); // IndexBatchException inherits CloudException, so additional circuit breaker not needed AsyncPolicy circuitBreaker = Policy.Handle <CloudException>().CircuitBreakerAsync(500, TimeSpan.FromMinutes(1)); List <IAsyncPolicy> policies = new List <IAsyncPolicy>(8) { cloudExceptionRetry, circuitBreaker, indexBatchExceptionRetry }; if (chainedPolicies != null && chainedPolicies.Any()) { policies.AddRange(chainedPolicies); } AsyncPolicyWrap policyWrap = Policy.WrapAsync(policies.ToArray()); return(policyWrap); }
public ResilientHttpClient(IAsyncPolicy[] policies, ILogger <ResilientHttpClient> logger) { _client = new HttpClient(); _logger = logger; // Add Policies to be applied _policyWrapper = Policy.WrapAsync(policies); }
public ChargePatientHandler(ICustomer customer, int timeoutInSeconds, int maxRetries = 0) { TimeoutInSeconds = timeoutInSeconds; MaxRetries = maxRetries; var _timeoutPolicy = Policy.TimeoutAsync(TimeoutInSeconds, TimeoutStrategy.Pessimistic); var _retryPolicy = Policy.Handle <HttpRequestException>().RetryAsync(MaxRetries); _policyWrap = Policy.WrapAsync(_timeoutPolicy, _retryPolicy); _customer = customer; }
public void Generic_wraps_generic_using_instance_wrap_syntax_should_set_outer_inner() { AsyncPolicy <int> policyA = Policy.NoOpAsync <int>(); AsyncPolicy <int> policyB = Policy.NoOpAsync <int>(); AsyncPolicyWrap <int> wrap = policyA.WrapAsync(policyB); wrap.Outer.Should().BeSameAs(policyA); wrap.Inner.Should().BeSameAs(policyB); }
public void Wrapping_policies_using_static_wrap_strongly_typed_syntax_should_set_outer_inner() { AsyncPolicy <int> policyA = Policy.NoOpAsync <int>(); AsyncPolicy <int> policyB = Policy.NoOpAsync <int>(); AsyncPolicyWrap <int> wrap = Policy.WrapAsync(policyA, policyB); wrap.Outer.Should().BeSameAs(policyA); wrap.Inner.Should().BeSameAs(policyB); }
public static Module ModuleFactory(string s20SerialNumber, AsyncPolicyWrap policyWrap) { var sub20Interfaces = new Sub20Interfaces(); if (!string.IsNullOrEmpty(s20SerialNumber)) { return(ModuleFactory(new CSub20(s20SerialNumber, sub20Interfaces), policyWrap)); } throw new Exception($"Null or Empty Sub20 requested : {s20SerialNumber}"); }
internal static void SetUpPolicies(int retryCount, int retrySeconds, Func <IBaseMessage, Task> onFallBackAction, Func <IBaseMessage, Task> onErrorAction) { var fallBackPolicy = SetUpFallBackPolicy(onFallBackAction, onErrorAction); var retryPolicy = SetUpRetryPolicy(retryCount, retrySeconds); MessagingPolicy = fallBackPolicy.WrapAsync(retryPolicy); }
public Pullo(ILogger <Pullo> logger) { _logger = logger; _enumerables = new ConcurrentQueue <IEnumerable <Func <Task> > >(); _queue = new ConcurrentQueue <Func <Task> >(); _resiliencePolicy = Policy.WrapAsync(Policy.NoOpAsync(), Policy.NoOpAsync()); _localCancellation = CancellationTokenSource.CreateLinkedTokenSource(CancellationToken.None); _cancellation = CancellationTokenSource.CreateLinkedTokenSource(_localCancellation.Token); }
public MessageService(IMessageRepository messageRepository) { Trace.WriteLine("MessageService running"); _messageRepository = messageRepository; // Политика повторителя. _retryPolicy = Policy .Handle <Exception>() // retryCount - указывает, сколько раз вы хотите повторить попытку. // sleepDurationProvider - делегат, который определяет, как долго ждать перед повторной попыткой. .WaitAndRetryAsync(2, retryAttempt => { // Экспоненциальное время ожидания. var timeToWait = TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)); Trace.WriteLine($"Waiting {timeToWait.TotalSeconds} seconds"); return(timeToWait); }); // Политика выключателя. // Обращаемся к репозиторию, через объединение политик. // В случае ошибки, выключатель перейдет в открытое состояние, на указанное время. _circuitBreakerPolicy = Policy <string> .Handle <Exception>() // exceptionsAllowedBeforeBreaking - указывает, сколько исключений подряд вызовет разрыв цепи. // durationOfBreak - указывает, как долго цепь будет оставаться разорванной. .CircuitBreakerAsync(1, TimeSpan.FromSeconds(30), // onBreak - является делегатом, позволяет выполнить какое-то действие, когда цепь разорвана. (exception, timeSpan) => { Trace.WriteLine($"Circuit broken! {timeSpan}"); }, // onReset - является делегатом, позволяет выполнить какое-либо действие, когда канал сброшен () => { Trace.WriteLine("Circuit Reset!"); }); // Политика подмены исключения на ответ. // Игнорируем ошибку и выводим статические данные. var fallbackPolicy = Policy <string> .Handle <Exception>() .FallbackAsync(async token => { Trace.WriteLine("Return Fallback"); return(await new ValueTask <string>("Bypassing a request to the repository.")); }); // Объединение политик в одну. _policyWrap = Policy.WrapAsync(fallbackPolicy, _circuitBreakerPolicy); }
public async Task <ActionResult <IEnumerable <Team> > > GetSomeData(CancellationToken cancellationToken) { Context context = new Context(nameof(GetSomeData)).WithChaosSettings(chaosSettings); retries = 0; //https://github.com/PawelGerr/EntityFrameworkCore-Demos/blob/master/src/EntityFramework.Demo/Demos/NamedTransactionsDemo.cs //catch (InvalidOperationException ex) when ((ex.InnerException?.InnerException is SqlException sqlEx) && sqlEx.Number == 1205) var fault = new InvalidOperationException("Simmy injected a deadlockException"); var chaosPolicy = MonkeyPolicy.InjectExceptionAsync(with => with.Fault(fault) .InjectionRate(0.95) .Enabled() ); var retryPolicy = Policy.Handle <Exception>().WaitAndRetryAsync( 3, // Retry 3 times attempt => TimeSpan.FromMilliseconds(200), // Wait 200ms between each try. (exception, calculatedWaitDuration) => // Capture some info for logging! { // This is your new exception handler! // Tell the user what they've won! _logger.LogWarning(EventIds.DBReadFailure, exception, "hit an exception"); retries++; }); AsyncPolicyWrap faultAndRetryWrap = Policy.WrapAsync(retryPolicy, chaosPolicy); try { // Retry the following call according to the policy - 3 times. var something = await faultAndRetryWrap.ExecuteAsync <List <Team> >( async (context, cancellationToken) => // The Execute() overload takes a CancellationToken, but it happens the executed code does not honour it. { // This code is executed within the Policy var corr = context.CorrelationId; // Make a request and get a response // Display the response message on the console _logger.LogDebug("Getting some data: "); return(await _context.Teams.ToListAsync()); } , context , cancellationToken // The cancellationToken passed in to Execute() enables the policy instance to cancel retries, when the token is signalled. ); return(something); } catch (Exception e) { _logger.LogError("Request eventually failed with: " + e.Message); } return(BadRequest()); }
public Cache( CacheHandle handle, ILogger <Cache <T> > logger) { _handle = handle ?? throw new ArgumentNullException(nameof(handle)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _debugLoggingEnabled = logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug); _errorLoggingEnabled = logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Error); _getFallBack = _handle.getFallBack; _setFallBack = _handle.setFallBack; }
public WcfFunnyQuotesClient(IDiscoveryClient discoveryClient, IOptionsSnapshot <FunnyQuotesConfiguration> config) { var circuitBreaker = Policy .Handle <Exception>() .CircuitBreakerAsync(2, TimeSpan.FromMinutes(15)); var retryOnFailure = Policy.Handle <Exception>().RetryAsync(1); var timeout = Policy.TimeoutAsync(TimeSpan.FromSeconds(2)); _apiCallPolicy = Policy.WrapAsync(circuitBreaker, timeout, retryOnFailure); _config = config; _discoveryClient = new DiscoveryHttpClientHandlerBase(discoveryClient); }
public BackgroundShoppingCartService( IUnitOfWork unitOfWork, IHttpClientFactory clientFactory, IReportSaver reportSaver, IConfiguration configuration, IReadOnlyPolicyRegistry <string> registry) { _unitOfWork = unitOfWork; _httpClientFactory = clientFactory; _reportSaver = reportSaver; _onDeleteWebhookUrl = configuration.GetValue <string>("ShoppingCartOnDeleteWebhookUrl"); _webhookApiPolicy = registry.Get <AsyncPolicyWrap <HttpResponseMessage> >("webhookApiPolicy"); }
public Policies() { var retryPolicy = Policy .Handle <Exception>() .WaitAndRetryAsync(retryCount: NumberOfRetries, sleepDurationProvider: i => _pauseBetweenFailures, onRetry: ManageRetryException); var timeOutPolicy = Policy .TimeoutAsync(timeout: TimeSpan.FromMilliseconds(DefaultTimeOutMS), timeoutStrategy: TimeoutStrategy.Pessimistic, onTimeoutAsync: ManageTimeoutException); PolicyWrap = Policy.WrapAsync(retryPolicy, timeOutPolicy); }
public FetchClient(FetchFileOptions options, MetricsProvider metricsProvider, ILogger <FetchClient> logger) { _logger = logger; _maxRetryCount = options.MaxRetryCount; _maxBinarySize = options.MaxBinarySize; _fetchErrorsMetric = metricsProvider.GetFetchErrorsMetric(); _fetchRetriesMetric = metricsProvider.GetFetchRetriesMetric(); _fetchDurationMsMetric = metricsProvider.GetFetchDurationMsMetric(); _interruptedFetchRequestsMetric = metricsProvider.GetInterruptedFetchRequestsMetric(); var timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(options.MaxTimeoutMs), TimeoutStrategy.Optimistic); var retryPolicy = Policy.Handle <HttpRequestException>() .Or <TimeoutRejectedException>() .RetryAsync(_maxRetryCount, RetryHandler); _timeoutWithRetryPolicy = retryPolicy.WrapAsync(timeoutPolicy); }
public static AsyncPolicy GeneratePublishedIndexSearch(int retries = 15, TimeSpan?timespan = null) { var waitAndRetryPolicy = Policy.Handle <CloudException>(c => c.Message == "Another indexer invocation is currently in progress; concurrent invocations not allowed.") .WaitAndRetryAsync(retries, i => timespan ?? TimeSpan.FromSeconds(20)); AsyncFallbackPolicy fault = Policy.Handle <CloudException>() .FallbackAsync((cancellationToken) => Task.CompletedTask, onFallbackAsync: async e => { await Task.FromResult(true); }); AsyncPolicyWrap policyWrap = fault.WrapAsync(waitAndRetryPolicy); return(policyWrap); }
public async Task Outermost_policy_not_handling_exception_even_if_inner_policies_do_should_report_as_unhandled_exception() { var innerHandlingDBZE = Policy .Handle <DivideByZeroException>() .CircuitBreakerAsync(1, TimeSpan.Zero); var outerHandlingANE = Policy .Handle <ArgumentNullException>() .CircuitBreakerAsync(1, TimeSpan.Zero); AsyncPolicyWrap wrap = outerHandlingANE.WrapAsync(innerHandlingDBZE); PolicyResult executeAndCaptureResultOnPolicyWrap = await wrap.ExecuteAndCaptureAsync(() => { throw new DivideByZeroException(); }); executeAndCaptureResultOnPolicyWrap.Outcome.Should().Be(OutcomeType.Failure); executeAndCaptureResultOnPolicyWrap.FinalException.Should().BeOfType <DivideByZeroException>(); executeAndCaptureResultOnPolicyWrap.ExceptionType.Should().Be(ExceptionType.Unhandled); }
/// <summary> /// Initializes a new instance of the <see cref="ResilientForceClient"/> class. /// </summary> /// <param name="forceClient"></param> /// <param name="options"></param> /// <param name="logger"></param> public ResilientForceClient( Func <AsyncExpiringLazy <ForceClient> > forceClient, IOptions <SalesforceConfiguration> options, ILogger <ResilientForceClient> logger) { if (forceClient == null) { throw new ArgumentNullException(nameof(forceClient)); } _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _forceClient = forceClient(); _options = options.Value; _policy = Policy.WrapAsync(GetAuthenticationRetryPolicy(), GetWaitAndRetryPolicy()); }
public HttpLoggerProcessor(HttpLoggerQueue queue, HttpLoggerService service, ILogger <HttpLoggerProcessor> logger) { _queue = queue; _service = service; _logger = logger; var retryPolicy = Policy .Handle <HttpRequestException>() .Or <OperationCanceledException>() .WaitAndRetryAsync(new[] { TimeSpan.FromMilliseconds(500), TimeSpan.FromSeconds(3) }); var circuitBreakerPolicy = Policy .Handle <HttpRequestException>() .Or <OperationCanceledException>() .CircuitBreakerAsync(exceptionsAllowedBeforeBreaking: 3, durationOfBreak: TimeSpan.FromMinutes(3)); _policy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy); }
public static Module ModuleFactory(ISub20 sub20, AsyncPolicyWrap policyWrap) { var i2C = new Sub20I2C(sub20); var gpioConfiguration = new GpioConfiguration(0x00380000, 0x00380000); IGpio gpio = new Sub20Gpio(sub20, gpioConfiguration); gpio.GpioInitialize(); var dutGpio = new DutGpio.DutGpio(null, gpio, new DutGpioBits(16, 17, 18)); var deviceIO = new DeviceIO(i2C, dutGpio, policyWrap); var cyclops = new Cyclops.Cyclops(deviceIO); var qsfp100GFRS = new Qsfp100G(deviceIO); var macom = new MaCom.MaCom(deviceIO); var module = new Module(deviceIO, qsfp100GFRS, cyclops, macom, policyWrap); return(module); }
public async Task Outermost_generic_policy_handling_result_should_report_as_PolicyWrap_handled_result() { var innerHandlingFaultAgain = Policy .HandleResult(ResultPrimitive.FaultAgain) .CircuitBreakerAsync(1, TimeSpan.Zero); var outerHandlingFault = Policy .HandleResult(ResultPrimitive.Fault) .CircuitBreakerAsync(1, TimeSpan.Zero); AsyncPolicyWrap <ResultPrimitive> wrap = outerHandlingFault.WrapAsync(innerHandlingFaultAgain); PolicyResult <ResultPrimitive> executeAndCaptureResultOnPolicyWrap = await wrap.ExecuteAndCaptureAsync(() => Task.FromResult(ResultPrimitive.Fault)); executeAndCaptureResultOnPolicyWrap.Outcome.Should().Be(OutcomeType.Failure); executeAndCaptureResultOnPolicyWrap.FaultType.Should().Be(FaultType.ResultHandledByThisPolicy); executeAndCaptureResultOnPolicyWrap.FinalHandledResult.Should().Be(ResultPrimitive.Fault); executeAndCaptureResultOnPolicyWrap.FinalException.Should().BeNull(); executeAndCaptureResultOnPolicyWrap.ExceptionType.Should().BeNull(); }
public async Task Outermost_generic_policy_not_handling_result_even_if_inner_policies_do_should_not_report_as_handled() { var innerHandlingFaultAgain = Policy .HandleResult(ResultPrimitive.FaultAgain) .CircuitBreakerAsync(1, TimeSpan.Zero); var outerHandlingFault = Policy .HandleResult(ResultPrimitive.Fault) .CircuitBreakerAsync(1, TimeSpan.Zero); AsyncPolicyWrap <ResultPrimitive> wrap = outerHandlingFault.WrapAsync(innerHandlingFaultAgain); PolicyResult <ResultPrimitive> executeAndCaptureResultOnPolicyWrap = await wrap.ExecuteAndCaptureAsync(() => Task.FromResult(ResultPrimitive.FaultAgain)); executeAndCaptureResultOnPolicyWrap.Outcome.Should().Be(OutcomeType.Successful); executeAndCaptureResultOnPolicyWrap.FinalHandledResult.Should().Be(default(ResultPrimitive)); executeAndCaptureResultOnPolicyWrap.FaultType.Should().BeNull(); executeAndCaptureResultOnPolicyWrap.FinalException.Should().BeNull(); executeAndCaptureResultOnPolicyWrap.ExceptionType.Should().BeNull(); }
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); }
public static AsyncPolicyWrap <HttpResponseMessage> GetRequestPolicy(IMemoryCache memoryCache = null, int cacheSeconds = 0, int additionalRetries = 0, int requestTimeoutSeconds = 100) { AsyncCachePolicy cache = null; if (memoryCache != null) { var memoryCacheProvider = new MemoryCacheProvider(memoryCache); cache = Policy.CacheAsync(memoryCacheProvider, TimeSpan.FromSeconds(cacheSeconds)); } int[] httpStatusCodesWorthRetrying = { StatusCodes.Status408RequestTimeout, StatusCodes.Status429TooManyRequests, //StatusCodes.Status500InternalServerError, StatusCodes.Status502BadGateway, StatusCodes.Status503ServiceUnavailable, StatusCodes.Status504GatewayTimeout }; var waitAndRetryPolicy = Policy .Handle <HttpRequestException>() //HttpClient Timeout or CancellationToken .Or <TimeoutRejectedException>() .OrResult <HttpResponseMessage>(r => httpStatusCodesWorthRetrying.Contains((int)r.StatusCode)) .WaitAndRetryAsync(additionalRetries, retryAttempt => TimeSpan.FromSeconds(1)); //https://github.com/App-vNext/Polly/wiki/Timeout var requestTimeout = Policy.TimeoutAsync(TimeSpan.FromSeconds(requestTimeoutSeconds)); //https://github.com/App-vNext/Polly/wiki/PolicyWrap AsyncPolicyWrap <HttpResponseMessage> policyWrap = null; if (cache != null) { policyWrap = cache.WrapAsync(waitAndRetryPolicy).WrapAsync(requestTimeout); } else { policyWrap = waitAndRetryPolicy.WrapAsync(requestTimeout); } return(policyWrap); }