public TResult TryExecute <TResult>(Func <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)
                .WaitAndRetry(
                    // 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)
                .CircuitBreaker(
                    // 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.Wrap(policies);

            return(policyWrap.Execute <TResult>(actionToPerform));
        }