Ejemplo n.º 1
0
        public T Execute <T>(Func <T> action, string dependencyName, FaultToleranceType toleranceType)
        {
            Policy policy;

            switch (toleranceType)
            {
            case FaultToleranceType.Retry:
                policy = (Policy)policies.GetOrAdd($"{dependencyName}-sync", GetLimitedRetryPolicy(dependencyName));
                break;

            case FaultToleranceType.WaitRetry:
                policy = (Policy)policies.GetOrAdd($"{dependencyName}-sync", GetWaitAndRetryPolicy(dependencyName));
                break;

            case FaultToleranceType.RetryWithCircuitBreaker:
                policy = (Policy)policies.GetOrAdd($"{dependencyName}-sync", GetRetryWithCircuitBreaker(dependencyName));
                break;

            case FaultToleranceType.CircuitBreaker:
                policy = (Policy)policies.GetOrAdd($"{dependencyName}-sync", GetCircuitBreaker(dependencyName));
                break;

            case FaultToleranceType.Timeout:
                policy = (Policy)policies.GetOrAdd($"{dependencyName}-sync", Policy.Timeout(strategy.Timeout, TimeoutStrategy.Pessimistic));
                break;

            case FaultToleranceType.NoPolicy:
            default:
                policy = Policy.NoOp();
                break;
            }

            return(policy.Execute(action));
        }
Ejemplo n.º 2
0
        public void ExecuteTestWithPredicate(string dependencyName, FaultToleranceType toleranceType)
        {
            //Assign
            var strategy   = new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider());
            var fakeLogger = A.Fake <IApplicationLogger>();

            //Act
            var actor = new TolerancePolicy(fakeLogger, strategy);

            //Assert
            //Assert
            switch (toleranceType)
            {
            case FaultToleranceType.WaitRetry:
            case FaultToleranceType.RetryWithCircuitBreaker:
                var         executedNumberOfTimes = 0;
                Func <Task> result2 = async() =>
                {
                    await actor.ExecuteAsync(
                        () => Task.FromResult(executedNumberOfTimes++),
                        a => a < strategy.Retry,
                        dependencyName,
                        toleranceType);
                };

                result2.Awaiting(async a => await a()).Should().NotThrow();
                executedNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            case FaultToleranceType.CircuitBreaker:

                Func <Task> result3 = async() =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            await actor.ExecuteAsync(() => ThrowEx(), a => idx < strategy.AllowedFaults, dependencyName, toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };
                result3.Awaiting(async a => await a()).Should().Throw <BrokenCircuitException>();
                break;

            default:
                Assert.False(true, "Missing implementation");
                break;
            }
        }
Ejemplo n.º 3
0
        public void ExecuteTest(string dependencyName, FaultToleranceType toleranceType)
        {
            //Assign
            var strategy   = new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider());
            var fakeLogger = A.Fake <IApplicationLogger>();

            //Act
            var actor = new TolerancePolicy(fakeLogger, strategy);

            //Assert
            switch (toleranceType)
            {
            case FaultToleranceType.Timeout:
                Action result1 = () => actor.Execute(() =>
                {
                    SystemClock.Sleep(TimeSpan.FromSeconds(strategy.Timeout.Seconds + 1), CancellationToken.None);
                    return(dependencyName);
                },
                                                     dependencyName,
                                                     toleranceType);

                result1.Should().Throw <TimeoutRejectedException>();
                break;

            case FaultToleranceType.Retry:
                var    executedNumberOfTimes = 0;
                Action result2 = () => actor.Execute(() =>
                {
                    executedNumberOfTimes++;
                    return(ThrowEx());
                },
                                                     dependencyName,
                                                     toleranceType);

                result2.Should().Throw <NotImplementedException>();
                executedNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            case FaultToleranceType.WaitRetry:
                TimeSpan delayResult     = default;
                var      exNumberOfTimes = 0;
                Action   resultWait      = () =>
                {
                    var delay = Stopwatch.StartNew();
                    try
                    {
                        actor.Execute(
                            () =>
                        {
                            exNumberOfTimes++;
                            return(ThrowEx());
                        },
                            dependencyName,
                            toleranceType);
                    }
                    finally
                    {
                        delay.Stop();
                        delayResult = delay.Elapsed;
                    }
                };

                resultWait.Should().Throw <NotImplementedException>();
                exNumberOfTimes.Should().Be(strategy.Retry + 1);
                delayResult.Should().BeCloseTo(TimeSpan.FromSeconds(strategy.Wait.Seconds * strategy.Retry), Precision);
                break;

            case FaultToleranceType.CircuitBreaker:
                Action result3 = () =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            actor.Execute(() => ThrowEx(), dependencyName, toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result3.Should().Throw <BrokenCircuitException>();
                break;

            case FaultToleranceType.RetryWithCircuitBreaker:
                var    retriedBeforeBreakingCircuit = 0;
                Action result4 = () =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            actor.Execute(() =>
                            {
                                retriedBeforeBreakingCircuit++;
                                return(ThrowEx());
                            },
                                          dependencyName,
                                          toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result4.Should().Throw <BrokenCircuitException>();
                retriedBeforeBreakingCircuit.Should().Be(strategy.AllowedFaults * (strategy.Retry + 1));
                break;

            default:
                Assert.False(true, "Missing implementation");
                break;
            }
        }
Ejemplo n.º 4
0
        public void ExecuteAsyncTest(string dependencyName, FaultToleranceType toleranceType)
        {
            //Assign
            var strategy   = new TransientFaultHandlingStrategy(new InMemoryConfigurationProvider());
            var fakeLogger = A.Fake <IApplicationLogger>();

            //Act
            var actor = new TolerancePolicy(fakeLogger, strategy);

            //Assert
            switch (toleranceType)
            {
            case FaultToleranceType.Timeout:
                Func <Task> result1 = async() => await actor.ExecuteAsync(() => SystemClock.SleepAsync(TimeSpan.FromSeconds(strategy.Timeout.Seconds + 1), CancellationToken.None).ContinueWith(_ => dependencyName), dependencyName, toleranceType);

                result1.Awaiting(async a => await a()).Should().Throw <TimeoutRejectedException>();
                break;

            case FaultToleranceType.Retry:
                var         executedNumberOfTimes = 0;
                Func <Task> result2 = async() => await actor.ExecuteAsync(() =>
                {
                    executedNumberOfTimes++;
                    return(ThrowEx());
                },
                                                                          dependencyName,
                                                                          toleranceType);

                result2.Awaiting(async a => await a()).Should().Throw <NotImplementedException>();
                executedNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            case FaultToleranceType.CircuitBreaker:
                Func <Task> result3 = async() =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            await actor.ExecuteAsync(() => ThrowEx(), dependencyName, toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result3.Awaiting(async a => await a()).Should().Throw <BrokenCircuitException>();
                break;

            case FaultToleranceType.RetryWithCircuitBreaker:
                var         retriedBeforeBreakingCircuit = 0;
                Func <Task> result4 = async() =>
                {
                    int idx = 0;
                    while (idx++ <= strategy.AllowedFaults)
                    {
                        try
                        {
                            await actor.ExecuteAsync(() =>
                            {
                                retriedBeforeBreakingCircuit++;
                                return(ThrowEx());
                            },
                                                     dependencyName,
                                                     toleranceType);
                        }
                        catch (NotImplementedException)
                        { }
                    }
                };

                result4.Awaiting(async a => await a()).Should().Throw <BrokenCircuitException>();
                retriedBeforeBreakingCircuit.Should().Be(strategy.AllowedFaults * (strategy.Retry + 1));
                break;

            case FaultToleranceType.WaitRetry:
                var         exNumberOfTimes = 0;
                Func <Task> result5         = async() =>
                {
                    await actor.ExecuteAsync(
                        () =>
                    {
                        exNumberOfTimes++;
                        return(ThrowEx());
                    },
                        dependencyName,
                        toleranceType);
                };

                result5.Awaiting(async a => await a()).Should().Throw <NotImplementedException>();
                exNumberOfTimes.Should().Be(strategy.Retry + 1);
                break;

            default:
                Assert.False(true, "Missing implementation");
                break;
            }
        }
 public async Task <HttpResponseMessage> DeleteAsync(string requestUri, Func <HttpResponseMessage, bool> predicate = null, FaultToleranceType toleranceType = FaultToleranceType.RetryWithCircuitBreaker)
 {
     return(await policy.ExecuteAsync(() => httpClient.DeleteAsync(new Uri(requestUri)), predicate ?? (response => !response.IsSuccessStatusCode), $"{typeof(TService).Name}-{nameof(DeleteAsync)}", toleranceType));
 }
 public async Task <HttpResponseMessage> PostAsync(string requestUri, string content, FaultToleranceType toleranceType = FaultToleranceType.RetryWithCircuitBreaker)
 {
     return(await policy.ExecuteAsync(() => httpClient.PostAsync(new Uri(requestUri), new StringContent(content, Encoding.UTF8, "application/json")), response => !response.IsSuccessStatusCode, $"{typeof(TService).Name}-{nameof(PostAsync)}", toleranceType));
 }
 public async Task <HttpResponseMessage> GetAsync(string requestUri, Func <HttpResponseMessage, bool> predicate, FaultToleranceType toleranceType = FaultToleranceType.RetryWithCircuitBreaker)
 {
     return(await policy.ExecuteAsync(() => httpClient.GetAsync(new Uri(requestUri)), predicate, $"{typeof(TService).Name}-{nameof(GetAsync)}", toleranceType));
 }
Ejemplo n.º 8
0
 public async Task <HttpResponseMessage> GetAsync(string requestUri, FaultToleranceType toleranceType = FaultToleranceType.RetryWithCircuitBreaker)
 {
     return(await policy.ExecuteAsync(() => httpClient.GetAsync(new Uri(requestUri)), response => !response.IsSuccessStatusCode, typeof(TService).Name, toleranceType));
 }
Ejemplo n.º 9
0
        public async Task <T> ExecuteAsync <T>(Func <Task <T> > action, Func <T, bool> predicate, string dependencyName, FaultToleranceType toleranceType)
        {
            Policy <T> policy;
            var        key = $"{dependencyName}-predicate";

            switch (toleranceType)
            {
            case FaultToleranceType.WaitRetry:
                policy = (Policy <T>)policies.GetOrAdd(key, GetWaitAndRetryPolicyAsync(dependencyName, predicate));
                break;

            case FaultToleranceType.RetryWithCircuitBreaker:
                policy = (Policy <T>)policies.GetOrAdd(key, GetRetryWithCircuitBreakerAsync(dependencyName, predicate));
                break;

            case FaultToleranceType.CircuitBreaker:
                policy = (Policy <T>)policies.GetOrAdd(key, GetCircuitBreakerAsync(dependencyName, predicate));
                break;

            case FaultToleranceType.Retry:
            case FaultToleranceType.Timeout:
            case FaultToleranceType.NoPolicy:
            default:
                return(await ExecuteAsync(action, dependencyName, toleranceType));
            }

            return(await policy.ExecuteAsync(action));
        }
Ejemplo n.º 10
0
        public async Task <T> ExecuteAsync <T>(Func <Task <T> > action, string dependencyName, FaultToleranceType toleranceType)
        {
            Policy policy;

            switch (toleranceType)
            {
            case FaultToleranceType.Retry:
                policy = (Policy)policies.GetOrAdd(dependencyName, GetLimitedRetryPolicyAsync(dependencyName));
                break;

            case FaultToleranceType.WaitRetry:
                policy = (Policy)policies.GetOrAdd(dependencyName, GetWaitAndRetryPolicyAsync(dependencyName));
                break;

            case FaultToleranceType.RetryWithCircuitBreaker:
                policy = (Policy)policies.GetOrAdd(dependencyName, GetRetryWithCircuitBreakerAsync(dependencyName));
                break;

            case FaultToleranceType.CircuitBreaker:
                policy = (Policy)policies.GetOrAdd(dependencyName, GetCircuitBreakerAsync(dependencyName));
                break;

            case FaultToleranceType.Timeout:
                policy = (Policy)policies.GetOrAdd(dependencyName, Policy.TimeoutAsync(strategy.Timeout, TimeoutStrategy.Pessimistic));
                break;

            default:
                policy = Policy.NoOpAsync();
                break;
            }

            return(await policy.ExecuteAsync(action));
        }