Пример #1
0
        public async Task <ServiceResultModel> PostAsync(string uri, string key, StringContent content, ReturnType returnType)
        {
            var httpResponse = await _retryPolicyWrapper.ExecuteAsync(async() => {
                _client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", key);

                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var requestMessage          = new HttpRequestMessage(HttpMethod.Post, uri);

                var response = await _client.PostAsync(uri, content);

                return(response);
            });

            var result = new ServiceResultModel {
                HttpStatusCode = (int)httpResponse.StatusCode
            };

            if (returnType == ReturnType.String)
            {
                result.Contents = await httpResponse.Content.ReadAsStringAsync();

                result.Headers = httpResponse.Headers;
            }

            if (returnType == ReturnType.Binary)
            {
                result.Binary = await httpResponse.Content.ReadAsByteArrayAsync();

                result.Headers = httpResponse.Headers;
            }


            return(result);
        }
        public async Task ExecuteAsync_MultiplePolicies_WorkAsExpected()
        {
            // cache
            string url    = "/api/cache";
            string result = await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey1")); // typically cache key would be dynamic

            string result2 = await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey1"));

            Assert.IsTrue(!string.IsNullOrWhiteSpace(result));
            Assert.AreEqual(result, result2);

            // inner timeout (500 ms), retry (5), outer timeout (this will exception as the inner timeouts will be retried enough times to trigger outer timeout)
            url = "/api/timeout/slow";
            bool timeout = false;

            try
            {
                await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey2"));
            }
            catch (TimeoutRejectedException)
            {
                timeout = true;
            }

            Assert.IsTrue(timeout);

            // trying this again will trip circuit breaker before we get a chance to hit the outer timeout
            bool circuitIsBroken = false;

            try
            {
                string result3 = await _policyWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey3"));
            }
            catch (BrokenCircuitException)
            {
                circuitIsBroken = true;
            }

            Assert.IsTrue(circuitIsBroken);

            // lets try a fallback
            url = "/api/circuitbreaker/success";
            var fallbackWrapper = FallbackPolicy <string>
                                  .Handle <Exception>()
                                  .FallbackAsync(context => Task.Run(() => "default"))
                                  .WrapAsync(_policyWrapper);

            string result4 = await fallbackWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey4"));

            Assert.AreEqual("default", result4);

            // let circuit breaker reset
            Task.Delay(3000).Wait();
            string result5 = await fallbackWrapper.ExecuteAsync(async context => await _client.GetStringAsync(url), new Context("CacheKey5"));

            Assert.IsTrue(!string.IsNullOrWhiteSpace(result5));
            Assert.AreNotEqual("default", result5);
        }
Пример #3
0
 public async Task RetryAsync(Func <Task> func)
 {
     if (_asyncSinglePolicy != null)
     {
         await _asyncSinglePolicy.ExecuteAsync(func).ConfigureAwait(false);
     }
     else if (_asyncPolicyWrap != null)
     {
         await _asyncPolicyWrap.ExecuteAsync(func).ConfigureAwait(false);
     }
     await func().ConfigureAwait(false);
 }
Пример #4
0
        public async Task Should_return_value_from_cache_and_not_execute_delegate_if_cache_holds_value_when_mid_policywrap()
        {
            const string valueToReturnFromCache     = "valueToReturnFromCache";
            const string valueToReturnFromExecution = "valueToReturnFromExecution";
            const string executionKey = "SomeExecutionKey";

            IAsyncCacheProvider stubCacheProvider = new StubCacheProvider();
            CachePolicy         cache             = Policy.CacheAsync(stubCacheProvider, TimeSpan.MaxValue);
            Policy     noop = Policy.NoOpAsync();
            PolicyWrap wrap = Policy.WrapAsync(noop, cache, noop);

            await stubCacheProvider.PutAsync(executionKey, valueToReturnFromCache, new Ttl(TimeSpan.MaxValue), CancellationToken.None, false).ConfigureAwait(false);

            bool delegateExecuted = false;

            (await wrap.ExecuteAsync(async() =>
            {
                delegateExecuted = true;
                await TaskHelper.EmptyTask.ConfigureAwait(false);
                return(valueToReturnFromExecution);
            }, new Context(executionKey))
             .ConfigureAwait(false))
            .Should().Be(valueToReturnFromCache);

            delegateExecuted.Should().BeFalse();
        }
Пример #5
0
        public async Task <ActionResult <HttpResponseMessage> > Get()
        {
            Func <Task <HttpResponseMessage> > myFun = async() => await CallFailesService();

            Action <DelegateResult <HttpResponseMessage>, CircuitState, TimeSpan, Context> onBreak = (exception, state, timespan, context)
                                                                                                     =>
            {
            };
            Action <Context> onReset = context
                                       =>
            {
            };
            Action onHalfOpen = ()
                                =>
            { };

            retryPolicy = Policy
                          .HandleResult <HttpResponseMessage>
                              (r => r.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                          .WaitAndRetryAsync(4, i => PauseBetweenFailures);

            breaker = Policy.HandleResult <HttpResponseMessage>
                          (r => r.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                      .CircuitBreakerAsync(2, PauseBetweenFailures, onBreak, onReset, onHalfOpen);

            myResilienceStrategy = Policy.WrapAsync(retryPolicy, breaker);



            var ret = await myResilienceStrategy.ExecuteAsync(async() => await myFun.Invoke());

            return(ret);
        }
        public async Task <string> GetStringAsync(string uri, string authorizationToken = null,
                                                  string authorizationMethod            = "Bearer")
        {
            PolicyWrap <string> policyWrap = Policies.WaitAndRetryPolicy
                                             .WrapAsync(Policies.CircuitBreakerPolicy)
                                             .WrapAsync(Policies.FallbackForCircuitBreaker)
                                             .WrapAsync(Policies.FallbackForAnyException);

            var requestMessage = new HttpRequestMessage(HttpMethod.Get, uri);

            if (authorizationToken != null)
            {
                requestMessage.Headers.Authorization =
                    new AuthenticationHeaderValue(authorizationMethod, authorizationToken);
            }

            async Task <string> Action()
            {
                var response = await _client.SendAsync(requestMessage);

                return(await response.Content.ReadAsStringAsync());
            }

            return(await policyWrap.ExecuteAsync(Action));
        }
Пример #7
0
 public async Task <string> GetAsync()
 {
     return(await _policyWrap.ExecuteAsync(() =>
     {
         return QueryAsync();
     }));
 }
Пример #8
0
        private Task <T> HttpInvoker <T>(Func <Task <T> > action)
        {
            if (_singlePolicy == null)
            {
                return(_policyWrapper.ExecuteAsync(action));
            }

            return(_singlePolicy.ExecuteAsync(action));
        }
Пример #9
0
        /// <summary>
        /// 重试并熔断
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fun"></param>
        /// <returns></returns>
        public async Task <T> ExecRetryBreakerAsync <T>(Func <Task <T> > fun)
        {
            var cb = _policyRetryBreakerAsync.GetPolicy <CircuitBreakerPolicy>();

            if (cb.CircuitState.HasFlag(CircuitState.Open))
            {
                throw new Exception("处于熔断状态");
            }

            return(await _policyRetryBreaker.ExecuteAsync(fun));
        }
Пример #10
0
        /// <inheritdoc />
        public async Task <(Stream stream, string mediaType)> FetchAsync(Uri fetchUri)
        {
            var stopwatch     = Stopwatch.StartNew();
            var policyContext = new Context(fetchUri.ToString());

            _logger.LogDebug("Start fetch request to {url}", fetchUri);
            using (var response = await _timeoutWithRetryPolicy.ExecuteAsync(FetchAction, policyContext, CancellationToken.None))
            {
                stopwatch.Stop();
                _fetchDurationMsMetric.Labels(fetchUri.Host).Observe(stopwatch.ElapsedMilliseconds);
                _logger.LogDebug("Fetch request executed in {elapsedMs} ms", stopwatch.ElapsedMilliseconds);

                if (!response.IsSuccessStatusCode)
                {
                    _fetchErrorsMetric.Inc();
                    var content = await response.Content.ReadAsStringAsync();

                    _logger.LogError("Got status {status} on {method} request to {url} with content: {content}", response.StatusCode, HttpMethod.Get, fetchUri, content);
                    throw new FetchRequestException(response.StatusCode, content);
                }

                if (response.Content.Headers.ContentLength > _maxBinarySize)
                {
                    throw new FetchResponseTooLargeException(response.Content.Headers.ContentLength.Value);
                }

                if (string.IsNullOrEmpty(response.Content.Headers.ContentType.MediaType))
                {
                    throw new FetchResponseContentTypeInvalidException("Content type in response is not specified");
                }

                var memoryStream = new MemoryStream();
                using (var responseStream = await response.Content.ReadAsStreamAsync())
                {
                    int readBytes;
                    var buffer = new byte[StreamCopyBufferSize];
                    do
                    {
                        readBytes = await responseStream.ReadAsync(buffer, 0, buffer.Length);

                        await memoryStream.WriteAsync(buffer, 0, readBytes);

                        if (memoryStream.Length > _maxBinarySize)
                        {
                            throw new FetchResponseTooLargeException(memoryStream.Length);
                        }
                    }while (readBytes > 0);
                }

                return(memoryStream, response.Content.Headers.ContentType.MediaType);
            }
        }
Пример #11
0
        private async Task <HttpResponseMessage> ExecuteWithResiliencePolicies(Func <Task <HttpResponseMessage> > action)
        {
            var result = await _policy.ExecuteAsync(async() =>
            {
                var response = await action();
                if (response.ReportsServerError())
                {
                    // Throwing in the case of server-side errors allows
                    // the circuit breaker to correclty open, if necessary
                    throw new HttpRequestException($"{response.StatusCode} : {response.ReasonPhrase}");
                }
                return(response);
            });

            return(result);
        }
        public async Task <string> GetSiteNamePolly(CancellationToken cancellationToken)
        {
            var myException = "";

            try
            {
                return(await _policyWrap.ExecuteAsync(ct =>
                                                      ClientWrapper(), cancellationToken));
            }
            catch (Exception e)
            {
                myException = e.Message;
            }

            return(myException);
        }
        private async Task <InternalPersonDetails[]> MakeListPersonGroupRequest(string startPerson, string apiKey, string largegroupid, Guid requestId, PolicyWrap <HttpResponseMessage> policy)
        {
            string strResult = string.Empty;

            _log.Info($"Making ListPerson GET request requestId: {requestId} apiKey:{apiKey} start person {startPerson} ticks: {DateTime.Now.Ticks}");
            InternalPersonDetails[] result = null;
            // Request parameters.
            string requestParameters = largegroupid + "/persons";
            // Get the API URL and the API key from settings.
            var uriBase = ConfigurationManager.AppSettings["facePersonApiUrl"];

            // Configure the HttpClient request headers.
            _client.DefaultRequestHeaders.Clear();
            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
            // Assemble the URI for the REST API Call.
            var uri = uriBase + "/" + requestParameters;

            if (startPerson != string.Empty)
            {
                uri += "?start=" + startPerson;
            }
            try
            {
                // Execute the REST API call, implementing our resiliency strategy.
                HttpResponseMessage response = await policy.ExecuteAsync(() => _client.GetAsync(uri));

                // Get the JSON response.
                strResult = await response.Content.ReadAsStringAsync();

                result = await response.Content.ReadAsAsync <InternalPersonDetails[]>();

                _log.Info($"ListPersonGroup completed: requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            }
            catch (BrokenCircuitException bce)
            {
                _log.Error($"Could not contact the Face API service due to the following error: {bce.Message} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}", bce);
            }
            catch (Exception e)
            {
                _log.Error($"Critical error-MakeListPersonGroupRequest: {e.Message} requestId: {requestId} apiKey:{apiKey} string result:{strResult} ticks: {DateTime.Now.Ticks}", e);
            }

            return(result);
        }
Пример #14
0
 public override async Task HandleExceptionAsync(Func <CancellationToken, Task> action, CancellationToken actionCancellationToken = default(CancellationToken), Func <CancellationToken, Task> onExceptionCompensatingHandler = null, CancellationToken onExceptionCompensatingHandlerCancellationToken = default(CancellationToken))
 {
     try
     {
         await action(actionCancellationToken);
     }
     catch (Exception ex)
     {
         ExceptionHandlingUtility.WrapActionWithExceptionHandling(async() =>
         {
             if (CheckIfExceptionsNeedsToBePollyHandled(ex))
             {
                 PolicyWrap policyWrap = GetPolicyWrapWithProperFallbackActionSetForFallbackPoliciesAsync(ex, onExceptionCompensatingHandler);
                 await policyWrap.ExecuteAsync(action, actionCancellationToken);
             }
         }, _logger);
         await HandleExceptionWithThrowCondition(ex, onExceptionCompensatingHandler, onExceptionCompensatingHandlerCancellationToken);
     }
 }
 public override async Task HandleExceptionAsync(Func <CancellationToken, Task> action, CancellationToken actionCancellationToken = default(CancellationToken), Func <CancellationToken, Task> onExceptionCompensatingHandler = null, CancellationToken onExceptionCompensatingHandlerCancellationToken = default(CancellationToken))
 {
     try
     {
         await action(actionCancellationToken);
     }
     catch (Exception ex)
     {
         ExceptionHandlingUtility.WrapActionWithExceptionHandling(async() =>
         {
             if (_splittedTransientFailureExceptions.IsNotNullOrEmpty() && _splittedTransientFailureExceptions.Contains(ex.GetType().Name) && _policies.IsNotNullOrEmpty())
             {
                 PolicyWrap policyWrap = GetPolicyWrapWithProperFallbackActionSetForFallbackPoliciesAsync(ex, onExceptionCompensatingHandler);
                 await policyWrap.ExecuteAsync(action, actionCancellationToken);
             }
         }, _logger);
         await HandleExceptionWithThrowCondition(ex, onExceptionCompensatingHandler, onExceptionCompensatingHandlerCancellationToken);
     }
 }
Пример #16
0
        private async Task <FaceDetectResult[]> MakeFaceDetectRequest(byte[] imageBytes, string apiKey, Guid requestId, PolicyWrap <HttpResponseMessage> policy)
        {
            _log.Info($"Making detect request requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            string strResult = string.Empty;

            FaceDetectResult[] result = null;
            // Request parameters.
            const string requestParameters = "returnFaceId=true&returnFaceLandmarks=false";
            // Get the API URL and the API key from settings.
            var uriBase = ConfigurationManager.AppSettings["faceDetectApiUrl"];

            // Configure the HttpClient request headers.
            _client.DefaultRequestHeaders.Clear();
            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
            //_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            // Assemble the URI for the REST API Call.
            var uri = uriBase + "?" + requestParameters;

            try
            {
                // Execute the REST API call, implementing our resiliency strategy.
                HttpResponseMessage response = await policy.ExecuteAsync(() => _client.PostAsync(uri, FaceHelper.GetImageHttpContent(imageBytes)));

                // Get the JSON response.
                strResult = await response.Content.ReadAsStringAsync();

                result = await response.Content.ReadAsAsync <FaceDetectResult[]>();

                _log.Info($"detect completed: {strResult} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            }
            catch (BrokenCircuitException bce)
            {
                _log.Error($"Could not contact the Face API service due to the following error: {bce.Message} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}", bce);
            }
            catch (Exception e)
            {
                _log.Error($"Critical error-MakeFaceDetectRequest: {e.Message} requestId: {requestId} apiKey:{apiKey} string result:{strResult} ticks: {DateTime.Now.Ticks}", e);
            }

            return(result);
        }
Пример #17
0
        public async Task <IActionResult> Get(int id)
        {
            var    httpClient      = GetHttpClient();
            string requestEndpoint = $"inventory/{id}";

            HttpResponseMessage response = await _policyWrap.ExecuteAsync(
                async token => await httpClient.GetAsync(requestEndpoint, token), CancellationToken.None);

            if (response.IsSuccessStatusCode)
            {
                int itemsInStock = JsonConvert.DeserializeObject <int>(await response.Content.ReadAsStringAsync());
                return(Ok(itemsInStock));
            }

            if (response.Content != null)
            {
                return(StatusCode((int)response.StatusCode, response.Content.ReadAsStringAsync()));
            }
            return(StatusCode((int)response.StatusCode));
        }
Пример #18
0
        public async Task <ActionResult <HttpResponseMessage> > Get()
        {
            Func <Task <HttpResponseMessage> > myFun = async() => await CallFailesService();

            retryPolicy = Policy
                          .HandleResult <HttpResponseMessage>
                              (r => r.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                          .WaitAndRetryAsync(MaxRetryAttempts, i => PauseBetweenFailures);

            fallbackPolicy = Policy.HandleResult <HttpResponseMessage>
                                 (f => f.StatusCode == System.Net.HttpStatusCode.InternalServerError)
                             .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent(typeof(string), "the system under maintentance", new JsonMediaTypeFormatter())
            });

            myResilienceStrategy = Policy.WrapAsync(fallbackPolicy, retryPolicy);
            var ret = await myResilienceStrategy.ExecuteAsync(async() => await myFun.Invoke());

            return(ret);
        }
Пример #19
0
        private async Task <FaceDetectResult[]> MakeFaceIdentifyRequest(FaceIdentifyRequest req, string apiKey, Guid requestId, PolicyWrap <HttpResponseMessage> policy)
        {
            string        strResult = string.Empty;
            StringBuilder faceids   = new StringBuilder();

            req.FaceIds.ToList().ForEach(s => faceids.Append(s + " "));
            _log.Info($"Making identify request faceids: {faceids} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            FaceDetectResult[] result = null;
            // Get the API URL and the API key from settings.
            var uri = ConfigurationManager.AppSettings["faceIdentifyApiUrl"];

            // Configure the HttpClient request headers.
            _client.DefaultRequestHeaders.Clear();
            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
            //_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            try
            {
                // Execute the REST API call, implementing our resiliency strategy.
                HttpResponseMessage response = await policy.ExecuteAsync(() => _client.PostAsync(uri, FaceHelper.GetIdentifyHttpContent(req)));

                // Get the JSON response.
                strResult = await response.Content.ReadAsStringAsync();

                result = await response.Content.ReadAsAsync <FaceDetectResult[]>();

                _log.Info($"identify completed: {strResult} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}");
            }
            catch (BrokenCircuitException bce)
            {
                _log.Error($"Could not contact the Face API service due to the following error: {bce.Message} requestId: {requestId} apiKey:{apiKey} ticks: {DateTime.Now.Ticks}", bce);
            }
            catch (Exception e)
            {
                _log.Error($"Critical error-MakeFaceIdentifyRequest: {e.Message} requestId: {requestId} apiKey:{apiKey} string result:{strResult} ticks: {DateTime.Now.Ticks}", e);
            }

            return(result);
        }
        public async Task <TOut> Execute <TOut>(
            Func <Task <TOut> > actionToExecute)
        {
            var retryPolicy = Policy <TOut> .Handle <HttpRequestException>().WaitAndRetryAsync(resilienceSettings.RetryCount, (i) => TimeSpan.FromMilliseconds(i * 1000),
                                                                                               (result, retryDelay) =>
            {
                logger.Error("The service call to failed with Error {@ex}", $"Retrying in...{retryDelay} s", result.Exception);
            });

            var circuitBreakerPolicy = Policy <TOut> .Handle <HttpRequestException>().CircuitBreakerAsync(resilienceSettings.NumberOfErrorsBeforeBreakingCircuit, TimeSpan.FromSeconds(resilienceSettings.NumberOfSecondsToKeepCircuitBroken),
                                                                                                          (result, timespan) =>
            {
                logger.Warning("Circuit Breaker opened! Result: {@result}", result);
            },
                                                                                                          () =>
            {
                logger.Warning("Circuit Breaker reset!");
            });

            PolicyWrap <TOut> policyWrapper = Policy.WrapAsync(new IAsyncPolicy <TOut>[] { retryPolicy, circuitBreakerPolicy });
            var response = await policyWrapper.ExecuteAsync(actionToExecute);

            return(response);
        }
        public override async Task <TReturn> HandleExceptionAsync <TReturn>(Func <CancellationToken, Task <TReturn> > func, CancellationToken funcCancellationToken = default(CancellationToken), Func <CancellationToken, Task> onExceptionCompensatingHandler = null, CancellationToken onExceptionCompensatingHandlerCancellationToken = default(CancellationToken))
        {
            Task <TReturn> returnValue = default(Task <TReturn>);

            try
            {
                returnValue = await func(funcCancellationToken) as Task <TReturn>;
            }
            catch (Exception ex)
            {
                returnValue = await ExceptionHandlingUtility.WrapFuncWithExceptionHandling(async() =>
                {
                    if (_splittedTransientFailureExceptions.IsNotNullOrEmpty() && _splittedTransientFailureExceptions.Contains(ex.GetType().Name) && _policies.IsNotNullOrEmpty())
                    {
                        PolicyWrap 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);
        }
Пример #22
0
        public override async Task <TReturn> HandleExceptionAsync <TReturn>(Func <CancellationToken, Task <TReturn> > func, CancellationToken funcCancellationToken = default(CancellationToken), Func <CancellationToken, Task> onExceptionCompensatingHandler = null, CancellationToken onExceptionCompensatingHandlerCancellationToken = default(CancellationToken))
        {
            Task <TReturn> returnValue = default(Task <TReturn>);

            try
            {
                returnValue = await func(funcCancellationToken) as Task <TReturn>;
            }
            catch (Exception ex)
            {
                returnValue = await ExceptionHandlingUtility.WrapFuncWithExceptionHandling(async() =>
                {
                    if (CheckIfExceptionsNeedsToBePollyHandled(ex))
                    {
                        PolicyWrap 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);
        }
Пример #23
0
 public async Task ExecuteAsync(Func <Task> action)
 {
     await policies.ExecuteAsync(action);
 }
 async Task <HttpResponseMessage> HttpInvoker(Func <Task <HttpResponseMessage> > operation)
 {
     return(await policyWrap.ExecuteAsync(operation));
 }
        public override async Task ExecuteAsync(CancellationToken cancellationToken, IProgress <DemoProgress> progress)
        {
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }

            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            eventualSuccesses               = 0;
            retries                         = 0;
            eventualFailuresDueToTimeout    = 0;
            eventualFailuresForOtherReasons = 0;

            progress.Report(ProgressWithMessage(typeof(AsyncDemo09_Wrap_Fallback_Timeout_WaitAndRetry).Name));
            progress.Report(ProgressWithMessage("======"));
            progress.Report(ProgressWithMessage(String.Empty));

            Stopwatch watch = null;

            // Define our timeout policy: time out after 2 seconds.  We will use the pessimistic timeout strategy, which forces a timeout - even when the underlying delegate doesn't support it.
            var timeoutPolicy = Policy
                                .TimeoutAsync(TimeSpan.FromSeconds(2), TimeoutStrategy.Pessimistic);

            // Define our waitAndRetry policy: keep retrying with 4 second gaps.  This is (intentionally) too long: to demonstrate that the timeout policy will time out on this before waiting for the retry.
            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>() // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromSeconds(4),
                (exception, calculatedWaitDuration) =>
            {
                progress.Report(ProgressWithMessage(".Log,then retry: " + exception.Message, Color.Yellow));
                retries++;
            });

            // Define a fallback policy: provide a nice substitute message to the user, if we found the call was rejected due to the timeout policy.
            FallbackPolicy <String> fallbackForTimeout = Policy <String>
                                                         .Handle <TimeoutRejectedException>()
                                                         .FallbackAsync(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [Fallback for timeout]",
                onFallbackAsync: async b =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches failed with: " + b.Exception.Message + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresDueToTimeout++;
            }
                );

            // Define a fallback policy: provide a substitute string to the user, for any exception.
            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .FallbackAsync(
                fallbackAction: /* Demonstrates fallback action/func syntax */ async ct =>
            {
                await Task.FromResult(true);
                /* do something else async if desired */
                return("Please try again later [Fallback for any exception]");
            },
                onFallbackAsync: async e =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches eventually failed with: " + e.Exception.Message + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresForOtherReasons++;
            }
                );

            // Compared to previous demo08: here we use *instance* wrap syntax, to wrap all in one go.
            PolicyWrap <String> policyWrap = fallbackForAnyException.WrapAsync(fallbackForTimeout).WrapAsync(timeoutPolicy).WrapAsync(waitAndRetryPolicy);

            using (var client = new HttpClient())
            {
                totalRequests = 0;
                bool internalCancel = false;

                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Manage the call according to the whole policy wrap
                        string response = await policyWrap.ExecuteAsync(ct =>
                                                                        client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests), cancellationToken);

                        watch.Stop();

                        progress.Report(ProgressWithMessage("Response: " + response + "(after " + watch.ElapsedMilliseconds + "ms)", Color.Green));

                        eventualSuccesses++;
                    }
                    catch (Exception e) // try-catch not needed, now that we have a Fallback.Handle<Exception>.  It's only been left in to *demonstrate* it should never get hit.
                    {
                        throw new InvalidOperationException("Should never arrive here.  Use of fallbackForAnyException should have provided nice fallback value for any exceptions.", e);
                    }

                    // Wait half second
                    await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }
        public static async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            Console.WriteLine(typeof(AsyncDemo07_WaitAndRetryNestingCircuitBreakerUsingPolicyWrap).Name);
            Console.WriteLine("=======");
            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            var client            = new HttpClient();
            int eventualSuccesses = 0;
            int retries           = 0;
            int eventualFailuresDueToCircuitBreaking = 0;
            int eventualFailuresForOtherReasons      = 0;

            // Define our waitAndRetry policy: keep retrying with 200ms gaps.
            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>(e => !(e is BrokenCircuitException)) // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromMilliseconds(200),
                (exception, calculatedWaitDuration) =>
            {
                // This is your new exception handler!
                // Tell the user what they've won!
                ConsoleHelper.WriteLineInColor(".Log,then retry: " + exception.Message, ConsoleColor.Yellow);
                retries++;
            });

            // Define our CircuitBreaker policy: Break if the action fails 4 times in a row.
            var circuitBreakerPolicy = Policy
                                       .Handle <Exception>()
                                       .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 4,
                durationOfBreak: TimeSpan.FromSeconds(3),
                onBreak: (ex, breakDelay) =>
            {
                ConsoleHelper.WriteLineInColor(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ConsoleColor.Magenta);
                ConsoleHelper.WriteLineInColor("..due to: " + ex.Message, ConsoleColor.Magenta);
            },
                onReset: () => ConsoleHelper.WriteLineInColor(".Breaker logging: Call ok! Closed the circuit again!", ConsoleColor.Magenta),
                onHalfOpen: () => ConsoleHelper.WriteLineInColor(".Breaker logging: Half-open: Next call is a trial!", ConsoleColor.Magenta)
                );

            // New for demo07: combine the waitAndRetryPolicy and circuitBreakerPolicy into a PolicyWrap.
            PolicyWrap policyWrap = Policy.WrapAsync(waitAndRetryPolicy, circuitBreakerPolicy);

            int i = 0;

            // Do the following until a key is pressed
            while (!Console.KeyAvailable && !cancellationToken.IsCancellationRequested)
            {
                i++;
                Stopwatch watch = new Stopwatch();
                watch.Start();

                try
                {
                    // Retry the following call according to the policy wrap
                    string msg = await policyWrap.ExecuteAsync <String>(ct =>
                    {
                        // This code is executed through both policies in the wrap: WaitAndRetry outer, then CircuitBreaker inner.  Demo 06 shows a broken-out version of what this is equivalent to.

                        return(client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + i));
                    }, cancellationToken);

                    watch.Stop();

                    // Display the response message on the console
                    ConsoleHelper.WriteInColor("Response : " + msg, ConsoleColor.Green);
                    ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Green);

                    eventualSuccesses++;
                }
                catch (BrokenCircuitException b)
                {
                    watch.Stop();
                    ConsoleHelper.WriteInColor("Request " + i + " failed with: " + b.GetType().Name, ConsoleColor.Red);
                    ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red);
                    eventualFailuresDueToCircuitBreaking++;
                }
                catch (Exception e)
                {
                    watch.Stop();
                    ConsoleHelper.WriteInColor("Request " + i + " eventually failed with: " + e.Message, ConsoleColor.Red);
                    ConsoleHelper.WriteLineInColor(" (after " + watch.ElapsedMilliseconds + "ms)", ConsoleColor.Red);
                    eventualFailuresForOtherReasons++;
                }

                // Wait half second
                await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken);
            }

            Console.WriteLine("");
            Console.WriteLine("Total requests made                     : " + i);
            Console.WriteLine("Requests which eventually succeeded     : " + eventualSuccesses);
            Console.WriteLine("Retries made to help achieve success    : " + retries);
            Console.WriteLine("Requests failed early by broken circuit : " + eventualFailuresDueToCircuitBreaking);
            Console.WriteLine("Requests which failed after longer delay: " + eventualFailuresForOtherReasons);
        }
 private Task <T> HttpInvoker <T>(Func <Task <T> > action) =>
 // Executes the action applying all
 // the policies defined in the wrapper
 _policyWrapper.ExecuteAsync(() => action());
Пример #28
0
        public override async Task ExecuteAsync(CancellationToken cancellationToken, IProgress <DemoProgress> progress)
        {
            if (cancellationToken == null)
            {
                throw new ArgumentNullException(nameof(cancellationToken));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }

            // Let's call a web api service to make repeated requests to a server.
            // The service is programmed to fail after 3 requests in 5 seconds.

            eventualSuccesses = 0;
            retries           = 0;
            eventualFailuresDueToCircuitBreaking = 0;
            eventualFailuresForOtherReasons      = 0;

            progress.Report(ProgressWithMessage(typeof(AsyncDemo08_Wrap_Fallback_WaitAndRetry_CircuitBreaker).Name));
            progress.Report(ProgressWithMessage("======"));
            progress.Report(ProgressWithMessage(String.Empty));

            Stopwatch watch = null;

            // Define our waitAndRetry policy: keep retrying with 200ms gaps.
            var waitAndRetryPolicy = Policy
                                     .Handle <Exception>(e => !(e is BrokenCircuitException)) // Exception filtering!  We don't retry if the inner circuit-breaker judges the underlying system is out of commission!
                                     .WaitAndRetryForeverAsync(
                attempt => TimeSpan.FromMilliseconds(200),
                (exception, calculatedWaitDuration) =>
            {
                progress.Report(ProgressWithMessage(".Log,then retry: " + exception.Message, Color.Yellow));
                retries++;
            });

            // Define our CircuitBreaker policy: Break if the action fails 4 times in a row.
            var circuitBreakerPolicy = Policy
                                       .Handle <Exception>()
                                       .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 4,
                durationOfBreak: TimeSpan.FromSeconds(3),
                onBreak: (ex, breakDelay) =>
            {
                progress.Report(ProgressWithMessage(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", Color.Magenta));
                progress.Report(ProgressWithMessage("..due to: " + ex.Message, Color.Magenta));
            },
                onReset: () => progress.Report(ProgressWithMessage(".Breaker logging: Call ok! Closed the circuit again!", Color.Magenta)),
                onHalfOpen: () => progress.Report(ProgressWithMessage(".Breaker logging: Half-open: Next call is a trial!", Color.Magenta))
                );

            // Define a fallback policy: provide a nice substitute message to the user, if we found the circuit was broken.
            FallbackPolicy <String> fallbackForCircuitBreaker = Policy <String>
                                                                .Handle <BrokenCircuitException>()
                                                                .FallbackAsync(
                fallbackValue: /* Demonstrates fallback value syntax */ "Please try again later [message substituted by fallback policy]",
                onFallbackAsync: async b =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches failed with: " + b.Exception.Message
                                                    + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresDueToCircuitBreaking++;
            }
                );

            // Define a fallback policy: provide a substitute string to the user, for any exception.
            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .FallbackAsync(
                fallbackAction: /* Demonstrates fallback action/func syntax */ async ct =>
            {
                await Task.FromResult(true);
                /* do something else async if desired */
                return("Please try again later [Fallback for any exception]");
            },
                onFallbackAsync: async e =>
            {
                await Task.FromResult(true);
                watch.Stop();
                progress.Report(ProgressWithMessage("Fallback catches eventually failed with: " + e.Exception.Message
                                                    + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Red));
                eventualFailuresForOtherReasons++;
            }
                );

            // As demo07: we combine the waitAndRetryPolicy and circuitBreakerPolicy into a PolicyWrap, using the *static* Policy.Wrap syntax.
            PolicyWrap myResilienceStrategy = Policy.WrapAsync(waitAndRetryPolicy, circuitBreakerPolicy);

            // Added in demo08: we wrap the two fallback policies onto the front of the existing wrap too.  Demonstrates the *instance* wrap syntax. And the fact that the PolicyWrap myResilienceStrategy from above is just another Policy, which can be onward-wrapped too.
            // With this pattern, you can build an overall resilience strategy programmatically, reusing some common parts (eg PolicyWrap myResilienceStrategy) but varying other parts (eg Fallback) individually for different calls.
            PolicyWrap <String> policyWrap = fallbackForAnyException.WrapAsync(fallbackForCircuitBreaker.WrapAsync(myResilienceStrategy));

            // For info: Equivalent to: PolicyWrap<String> policyWrap = Policy.WrapAsync(fallbackForAnyException, fallbackForCircuitBreaker, waitAndRetryPolicy, circuitBreakerPolicy);

            totalRequests = 0;

            using (var client = new HttpClient())
            {
                bool internalCancel = false;
                // Do the following until a key is pressed
                while (!internalCancel && !cancellationToken.IsCancellationRequested)
                {
                    totalRequests++;
                    watch = new Stopwatch();
                    watch.Start();

                    try
                    {
                        // Manage the call according to the whole policy wrap
                        string response = await policyWrap.ExecuteAsync(ct =>
                                                                        client.GetStringAsync(Configuration.WEB_API_ROOT + "/api/values/" + totalRequests), cancellationToken);

                        watch.Stop();

                        // Display the response message on the console
                        progress.Report(ProgressWithMessage("Response : " + response + " (after " + watch.ElapsedMilliseconds + "ms)", Color.Green));

                        eventualSuccesses++;
                    }
                    catch (Exception e) // try-catch not needed, now that we have a Fallback.Handle<Exception>.  It's only been left in to *demonstrate* it should never get hit.
                    {
                        throw new InvalidOperationException("Should never arrive here.  Use of fallbackForAnyException should have provided nice fallback value for any exceptions.", e);
                    }

                    // Wait half second
                    await Task.Delay(TimeSpan.FromSeconds(0.5), cancellationToken);

                    internalCancel = TerminateDemosByKeyPress && Console.KeyAvailable;
                }
            }
        }
 public Task <MovieDetail> GetLatestMovieDetailListing(Movie movie)
 {
     return(_policyWrapMovieDetail.ExecuteAsync(() => GetMovieDetail(movie)));
 }
 public Task <MovieList> GetLatestMovieListing()
 {
     return(_policyWrap.ExecuteAsync(() => GetMovies()));
 }