コード例 #1
0
        private static async Task <HttpResponseMessage> TryExecuteAsync(Func <Task <HttpResponseMessage> > action)
        {
            var retryErrorCode = new HttpStatusCode[] { HttpStatusCode.BadRequest, HttpStatusCode.Unauthorized, HttpStatusCode.Forbidden, HttpStatusCode.InternalServerError };
            var response       = await Policy
                                 // When recieving a ApiException with status code 401 or 500
                                 .HandleResult <HttpResponseMessage>(message => retryErrorCode.Contains(message.StatusCode))
                                 // Retry count but execute some code before retrying
                                 .RetryAsync(3)
                                 .ExecuteAsync(action);

            response.EnsureSuccessStatusCode();

            return(response);
        }
コード例 #2
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            #region Discount gRPC client
            // Enable support for unencrypted HTTP2
            //AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
            //AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true);

            Random jitterer = new Random();

            var loggerFactory = LoggerFactory.Create(logging =>
            {
                logging.AddConsole();
                logging.SetMinimumLevel(LogLevel.Debug);
            });

            var serverErrors = new HttpStatusCode[] {
                HttpStatusCode.BadGateway,
                HttpStatusCode.GatewayTimeout,
                HttpStatusCode.ServiceUnavailable,
                HttpStatusCode.InternalServerError,
                HttpStatusCode.TooManyRequests,
                HttpStatusCode.RequestTimeout
            };

            var gRpcErrors = new StatusCode[] {
                StatusCode.DeadlineExceeded,
                StatusCode.Internal,
                StatusCode.NotFound,
                StatusCode.ResourceExhausted,
                StatusCode.Unavailable,
                StatusCode.Unknown
            };


            Func <HttpRequestMessage, IAsyncPolicy <HttpResponseMessage> > retryFunc = (request) =>
            {
                return(Policy.HandleResult <HttpResponseMessage>(r => {
                    var grpcStatus = StatusManager.GetStatusCode(r);
                    var httpStatusCode = r.StatusCode;

                    return (grpcStatus == null && serverErrors.Contains(httpStatusCode)) ||         // if the server send an error before gRPC pipeline
                    (httpStatusCode == HttpStatusCode.OK && gRpcErrors.Contains(grpcStatus.Value)); // if gRPC pipeline handled the request (gRPC always answers OK)
                })
                       .WaitAndRetryAsync(3, (input) => TimeSpan.FromSeconds(3 + input), (result, timeSpan, retryCount, context) =>
                {
                    var grpcStatus = StatusManager.GetStatusCode(result.Result);
                    Console.WriteLine($"Request failed with {grpcStatus}. Retry");
                }));
            };

            services.AddGrpcClient <DiscountProtoService.DiscountProtoServiceClient>(options =>
            {
                options.Address = new Uri(Configuration["GrpcSettings:DiscountUrl"]);
                options.ChannelOptionsActions.Add(channelOptions =>
                {
                    channelOptions.Credentials = ChannelCredentials.Insecure;
                });
            }).AddPolicyHandler(retryFunc);

            services.AddScoped <DiscountGrpcService>();

            #endregion

            #region Redis connection configuration
            services.AddStackExchangeRedisCache(options =>
            {
                options.Configuration = Configuration.GetValue <string>("CacheSettings:ConnectionString");
            });
            #endregion

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "Basket.API", Version = "v1"
                });
            });

            #region Data repositories registration
            services.AddScoped <IBasketRepository, BasketRepository>();
            #endregion
        }