public static void ForEach <TSource>(
     CircuitBreaker circuitBreaker,
     IEnumerable <TSource> source,
     Action <TSource> body,
     RetryOptions retryOptions = null)
 {
     foreach (var element in source)
     {
         var element1 = element;
         circuitBreaker.ExecuteWithRetries(
             () => body(element1),
             retryOptions);
     }
 }
        public static void ParallelForEach <TSource>(
            CircuitBreaker circuitBreaker,
            IEnumerable <TSource> source,
            Action <TSource> body,
            RetryOptions retryOptions       = null,
            ParallelOptions parallelOptions = null)
        {
            parallelOptions = parallelOptions ?? new ParallelOptions();

            Parallel.ForEach(
                source,
                parallelOptions,
                element =>
            {
                var element1 = element;
                circuitBreaker.ExecuteWithRetries(
                    () => body(element1),
                    retryOptions);
            });
        }
        public static void ExecuteWithRetries(this CircuitBreaker circuitBreaker, Action operation, RetryOptions retryOptions = null)
        {
            retryOptions = retryOptions ?? new RetryOptions();

            var attempts      = 0;
            var exceptions    = new List <Exception>();
            var handleFailure = HandleFailure(retryOptions, exceptions, attempts);

            while (attempts < retryOptions.AllowedRetries)
            {
                try
                {
                    if (!circuitBreaker.AllowedToAttemptExecute)
                    {
                        attempts = handleFailure(null);
                        continue;
                    }
                    circuitBreaker.Execute(operation);
                    return;
                }
                catch (OperationFailedException ex)
                {
                    attempts = handleFailure(ex.InnerException);
                }
            }
        }