private async Task <T> HttpInvoker <T>(string origin, Func <Task <T> > action)
        {
            var normalizedOrigin = NormalizeOrigin(origin);

            if (!_pocilyWrappers.TryGetValue(normalizedOrigin, out PolicyWrap policyWrap))
            {
                policyWrap = PolicyWrap.WrapAsync(_policyCreator(normalizedOrigin).ToArray());
                _pocilyWrappers.TryAdd(normalizedOrigin, policyWrap);
            }
            // Executes the action applying all
            // the policies defined in the wrapper

            return(await policyWrap.ExecuteAsync(action, new Context(normalizedOrigin)));
        }
        public async Task <TResult> TryExecuteAsync <TResult>(Func <Task <TResult> > actionToPerform, Func <Exception, bool> isRetryableException, int retryCount = 5, TimeSpan?retryAttempt = null, bool isLinearRetry = false)
        {
            var retryAttemptInSeconds = retryAttempt.HasValue ? retryAttempt.Value.Seconds : _defaultRetryAttemptInSeconds;
            var policies = new Policy[]
            {
                Policy.Handle <Exception>(isRetryableException)
                .WaitAndRetryAsync(
                    // number of retries
                    retryCount,
                    // backoff
                    retryTimeSpan => isLinearRetry ? TimeSpan.FromSeconds(retryAttemptInSeconds) : TimeSpan.FromSeconds(Math.Pow(2, retryAttemptInSeconds)),
                    // on retry
                    (exception, timeSpan, currentRetryCount, context) =>
                {
                    var msg = $"Retry ({currentRetryCount} of {retryCount}) due to: {exception}.";
                    _logger.LogWarning(msg);
                    _logger.LogDebug(msg);
                }),
                Policy.Handle <Exception>(isRetryableException)
                .CircuitBreakerAsync(
                    // number of exceptions before breaking circuit
                    _exceptionsAllowedBeforeBreaking,
                    // time circuit opened before retry
                    TimeSpan.FromMinutes(1),
                    (exception, duration) =>
                {
                    // on circuit opened
                    _logger.LogTrace("Circuit breaker opened");
                },
                    () =>
                {
                    // on circuit closed
                    _logger.LogTrace("Circuit breaker reset");
                })
            };

            var policyWrap = PolicyWrap.WrapAsync(policies);

            return(await policyWrap.ExecuteAsync <TResult>(actionToPerform));
        }