Exemplo n.º 1
0
        /*  This Handler must be configured as the PrimaryHttpMessageHandler to be able to
         *  be invoked during the Polly retry attempts and also swapout the
         *  OperationCanceledException when a request timeout occurs
         *  This Handler has a dual purpose for the above reason
         */
        protected async override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            using (var cts = GetCancellationTokenSource(request, cancellationToken))
            {
                try
                {
                    // If the Polly WaitAndRetryAsync handler has ran we will have the Retry Info
                    Polly.Context context   = request.GetPolicyExecutionContext();
                    RetryInfo     retryInfo = context.GetRetryInfo();
                    if (retryInfo != null)
                    {
                        // Log the fact that this request is due to a retry
                        _logger.LogWarning($"{DateTime.Now.ToString()} : Retrying {request.Method.ToString()} Request to Resource: {context["Resource"]}");
                    }
                    var response = await base.SendAsync(request, cts?.Token ?? cancellationToken);

                    return(response);
                }
                catch (OperationCanceledException ex) when(!cancellationToken.IsCancellationRequested)
                {
                    // Throw a TimeoutException with useful message and pass along the InnerException
                    var tex = new TimeoutException($"Request timed out, did not receive response within {(request.GetTimeout() ?? DefaultTimeout).TotalSeconds} seconds", ex.InnerException);

                    // Set the source of the exception
                    tex.Source = "TimeoutHandler";
                    throw tex;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }
Exemplo n.º 2
0
        static async Task PollyTest()
        {
            var atr = new CRL.Core.Remoting.PollyAttribute();

            //atr.TimeOutTime = TimeSpan.FromMilliseconds(100);
            atr.CircuitBreakerCount = 2;
            atr.RetryCount          = 1;
            var pollyCtx = new Polly.Context();
            var response = await PollyExtension.InvokeAsync <string>(atr, async() =>
            {
                //await Task.Delay(200);
                throw new Exception("has error");
                return(await Task.FromResult(new CRL.Core.Remoting.PollyExtension.PollyData <string>()
                {
                    Data = "ok"
                }));
            }, "");

            if (pollyCtx.ContainsKey("msg"))
            {
                Console.WriteLine(pollyCtx["msg"]);
            }

            //var str = PollyExtension.Invoke(atr, () =>
            // {
            //    throw new Exception("has error");
            //    //System.Threading.Thread.Sleep(200);
            //     return new PollyExtension.PollyData<string>() { Error = "ok" };
            // }, "test");
            Console.WriteLine(response.ToJson());
        }
Exemplo n.º 3
0
        /*  This Handler must be configured as the PrimaryHttpMessageHandler so that it
         *  gets invoked during the Polly retry attempts and is able to detect the original url and method
         *  This handler swaps out OperationCanceledException when a request timeout occurs
         *  This Handler adds info about the request into the Request Properties and Exception Data
         *  This Handler has 3 purposes but can't be split out as the above functions rely on it being the primary handler.
         */
        protected async override Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            using (var cts = GetCancellationTokenSource(request, cancellationToken))
            {
                try
                {
                    // If the Polly WaitAndRetryAsync handler has ran we will have the Retry Info
                    Polly.Context context   = request.GetPolicyExecutionContext();
                    RetryInfo     retryInfo = context.GetRetryInfo();
                    // The RequestUri and Method will always be the original ones as this code will not be hit
                    // if a redirection occurs as it is handles further down the chain.
                    if (retryInfo == null)
                    {
                        AugmentRequest(request);
                    }
                    else
                    {
                        // It's possible to detect a redirect here during a retry as the new request uses the redirected url
                        string requestUrl         = request?.RequestUri?.AbsoluteUri?.ToString();
                        string resourcePath       = (string)request.GetResourcePath();
                        string originalRequestUrl = (string)request.GetOriginalRequestUrl();
                        bool   isRedirected       = false;
                        if (!String.IsNullOrEmpty(requestUrl) && requestUrl != originalRequestUrl)
                        {
                            isRedirected = true;
                        }
                        string redirected            = isRedirected ? " Redirected" : "";
                        string originalRequestMethod = (string)request.GetOriginalRequestMethod();
                        // Log the fact that this request is due to a retry
                        _logger.LogWarning($"{DateTime.Now.ToString()} SendAsync: Retrying a Failed{redirected} {originalRequestMethod} Request to Resource: {resourcePath} {redirected}Url: {requestUrl}");
                    }
                    var response = await base.SendAsync(request, cts?.Token ?? cancellationToken);

                    return(response);
                }
                catch (OperationCanceledException ex) when(!cancellationToken.IsCancellationRequested)
                {
                    // Also catches TaskCanceledException as it is a subclass of OperationCanceledException
                    // Throw a TimeoutException with useful message and pass along the InnerException
                    var tex = new TimeoutException($"Request timed out, did not receive response within {(request.GetTimeout() ?? DefaultTimeout).TotalSeconds} seconds", ex.InnerException);

                    // Set the source of the exception
                    tex.Source = "TimeoutHandler";
                    AugmentException(tex, request);
                    throw tex;
                }
                catch (Exception ex)
                {
                    _logger.LogError($"{DateTime.Now.ToString()} SendAsync: Exception occurred in SendAsync() method, Request Url: {request?.RequestUri?.AbsoluteUri?.ToString()} Exception:\n{ex.ToString()}");
                    AugmentException(ex, request);
                    throw ex;
                }
            }
        }
Exemplo n.º 4
0
 public static void SetRetryInfo(this Polly.Context context, RetryInfo retryInfo)
 {
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     context[PropertyKeys.RetryInfoKey] = retryInfo;
 }
Exemplo n.º 5
0
        public static Task <HttpResponseMessage> FallbackValueFactory(Polly.Context context, CancellationToken cancellationToken)
        {
            var items    = Enumerable.Empty <WeatherForecast>();
            var json     = System.Text.Json.JsonSerializer.Serialize(items);
            var response = new HttpResponseMessage(System.Net.HttpStatusCode.OK)
            {
                Content = new StringContent(json, Encoding.UTF8, "application/json")
            };

            return(Task.FromResult(response));
        }
Exemplo n.º 6
0
        public static RetryInfo GetRetryInfo(this Polly.Context context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            object retryInfo = null;

            context.TryGetValue(PropertyKeys.RetryInfoKey, out retryInfo);
            if (retryInfo != null && retryInfo is RetryInfo)
            {
                return((RetryInfo)retryInfo);
            }
            return(null);
        }
Exemplo n.º 7
0
        protected async Task <T> SendRequestAsync <T>(PollyAttribute pollyAttr, Request.ImitateWebRequest request, string url, string httpMethod, string postArgs, string pollyKey, Func <string, T> dataCall)
        {
            var pollyCtx = new Polly.Context();
            //var response = await request.SendDataAsync(url, httpMethod.ToString(), postArgs);
            var pollyData = await PollyExtension.InvokeAsync(pollyAttr, async() =>
            {
                var res = await request.SendDataAsync(url, httpMethod.ToString(), postArgs);
                return(new PollyExtension.PollyData <string>()
                {
                    Data = res
                });
            }, pollyKey);

            if (!string.IsNullOrEmpty(pollyData.Error))
            {
                ThrowError(pollyData.Error, "500");
            }
            //转换为指定的类型
            return(dataCall(pollyData.Data));
        }
Exemplo n.º 8
0
 public static void SetPolicyExecutionContext(this System.Net.Http.HttpRequestMessage request, Polly.Context context)
 {
 }
Exemplo n.º 9
0
 protected virtual System.Threading.Tasks.Task <System.Net.Http.HttpResponseMessage> SendCoreAsync(System.Net.Http.HttpRequestMessage request, Polly.Context context, System.Threading.CancellationToken cancellationToken)
 {
     throw null;
 }