Пример #1
0
    public static IHttpClientBuilder UseTimeoutPolicy(this IHttpClientBuilder builder, TimeSpan timeout)
    {
        TimeoutPolicy <HttpResponseMessage>?timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(timeout);

        builder.AddPolicyHandler(timeoutPolicy);
        return(builder);
    }
Пример #2
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers(options => options.Filters.Add(typeof(ExceptionFilter)))
            // System.Text.Json does not support snake case strategy. Once it does (.NET 6), System.Text.Json should be used for better performance
            .AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                options.SerializerSettings.Converters.Add(new StringEnumConverter {
                    AllowIntegerValues = false
                });
                options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
                options.SerializerSettings.ContractResolver  = new DefaultContractResolver
                {
                    NamingStrategy = new SnakeCaseNamingStrategy()
                };

                JsonConvert.DefaultSettings = () => options.SerializerSettings;
            });

            services.AddAppMetricsToInfluxDb(Configuration)
            .AddConfiguredApiVersioning();

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo
                {
                    Title       = "Payment Getway API",
                    Description = "Payment Getway API",
                    Version     = "1.0"
                });

                options.ExampleFilters();

                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Documentation.xml"));
            }).AddSwaggerGenNewtonsoftSupport()
            .AddSwaggerExamplesFromAssemblyOf <Startup>();

            services.AddSingleton(sp =>
            {
                var cfg        = ConfigurationOptions.Parse(Configuration.GetValue <string>("RedisConnection"));
                var connection = ConnectionMultiplexer.Connect(cfg);

                return(connection);
            });
            services.AddTransient <PaymentService>();
            services.AddTransient <IPaymentRepository, InMemoryPaymentRepository>();
            services.AddTransient <IAcquiringBankConfigurationProvider>(p => new AcquiringBankConfigurationProvider(Configuration.GetSection(nameof(AcquiringBankConfiguration)).Get <AcquiringBankConfiguration>()));
            services.AddTransient <IPaymentRequestDuplicateChecker, PaymentRequestDuplicateChecker>();

            var httpPolicySettings          = Configuration.GetSection(nameof(HttpClientPolicySettings)).Get <HttpClientPolicySettings>();
            var acquiringBankCircuitBreaker = CircuitBreakerPolicy.Basic(httpPolicySettings.RetryCountBeforeBreaking, httpPolicySettings.DurationOfBreakInSeconds);

            services.AddHttpClient <IAcquiringBank, AcquiringBank>()
            .AddPolicyHandler((s, r) => Policy.WrapAsync(RetryPolicy.Basic(s.GetService <ILogger <IAcquiringBank> >(), r, httpPolicySettings.RetryCount),
                                                         RetryPolicy.HonouringRetry(s.GetService <ILogger <IAcquiringBank> >(), r, httpPolicySettings.RetryCount),
                                                         TimeoutPolicy.Basic(httpPolicySettings.RequestTimeoutInSeconds),
                                                         acquiringBankCircuitBreaker));

            services.Replace(ServiceDescriptor.Singleton <IHttpMessageHandlerBuilderFilter, LoggingFilter>());
        }
Пример #3
0
        public PollyQoSProvider(ReRoute reRoute, IOcelotLoggerFactory loggerFactory)
        {
            _logger = loggerFactory.CreateLogger <PollyQoSProvider>();

            _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.TimeoutValue), reRoute.QosOptionsOptions.TimeoutStrategy);

            _circuitBreakerPolicy = Policy
                                    .Handle <HttpRequestException>()
                                    .Or <TimeoutRejectedException>()
                                    .Or <TimeoutException>()
                                    .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: reRoute.QosOptionsOptions.ExceptionsAllowedBeforeBreaking,
                durationOfBreak: TimeSpan.FromMilliseconds(reRoute.QosOptionsOptions.DurationOfBreak),
                onBreak: (ex, breakDelay) =>
            {
                _logger.LogError(
                    ".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!", ex);
            },
                onReset: () =>
            {
                _logger.LogDebug(".Breaker logging: Call ok! Closed the circuit again.");
            },
                onHalfOpen: () =>
            {
                _logger.LogDebug(".Breaker logging: Half-open; next call is a trial.");
            }
                );

            _circuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy);
        }
Пример #4
0
        public void BaseTest3()
        {
            TimeoutPolicy policy = new TimeoutPolicy(TimeSpan.Zero);

            Assert.False(policy.IsValid());
            Assert.Null(policy.GetSync());
            Assert.Null(policy.GetAsync());
        }
Пример #5
0
        public void BaseTest1()
        {
            TimeoutPolicy policy = new TimeoutPolicy();

            Assert.False(policy.IsValid());
            Assert.Null(policy.GetSync());
            Assert.Null(policy.GetAsync());
            Assert.Equal(5, policy.Index);
        }
 public LoopAndPrintWithPollyTimeout()
 {
     timeoutPolicy = Policy
                     .Timeout(1, TimeoutStrategy.Pessimistic, onTimeout:
                              (context, span, t1, exception) =>
     {
         Console.WriteLine(exception.Message);
     });
 }
Пример #7
0
 static ProxyConfigurator()
 {
     //TODO: Change this to use a policy registry?
     RetryPolicy = HttpPolicyExtensions
                   .HandleTransientHttpError()
                   .RetryAsync(3);
     TimeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(10));
     NoOpPolicy    = Policy.NoOpAsync().AsAsyncPolicy <HttpResponseMessage>();
 }
Пример #8
0
 public CircuitBreakingHandler(int exceptionsAllowedBeforeBreaking,
                               TimeSpan durationOfBreak,
                               TimeSpan timeoutValue,
                               TimeoutStrategy timeoutStrategy = TimeoutStrategy.Pessimistic)
     : base(string.Format("Handler:{0}", nameof(T)))
 {
     _exceptionsAllowedBeforeBreaking = exceptionsAllowedBeforeBreaking;
     _durationOfBreak      = durationOfBreak;
     _timeoutBreakerPolicy = Policy.Timeout(timeoutValue, timeoutStrategy);
 }
Пример #9
0
        public void BaseTest4()
        {
            TimeoutPolicy policy = new TimeoutPolicy(TimeSpan.FromMilliseconds(2000));

            Assert.True(policy.IsValid());
            Assert.NotNull(policy.GetSync());
            Assert.NotNull(policy.GetAsync());

            Assert.Equal(TimeSpan.FromMilliseconds(2000).TotalMilliseconds, policy.TimeSpan.TotalMilliseconds);
        }
Пример #10
0
        public void BaseTest2()
        {
            TimeoutPolicy policy = new TimeoutPolicy(6);

            Assert.True(policy.IsValid());
            Assert.NotNull(policy.GetSync());
            Assert.NotNull(policy.GetAsync());

            Assert.Equal(6, policy.Seconds);
        }
Пример #11
0
        static void Wrap()
        {
            bool check = false;

            RetryPolicy waitAndRetryPolicy = Policy
                                             .Handle <Exception>()
                                             .Retry(6,
                                                    onRetry: (exception, retryCount) =>
            {
                Console.WriteLine($"====Retry===== : 呼叫 API 異常, 進行第 {retryCount} 次重試");
                if (retryCount == 5)
                {
                    check = true;
                }
            });

            TimeoutPolicy timeoutPolicys = Policy
                                           .Timeout(TimeSpan.FromMilliseconds(1000), TimeoutStrategy.Pessimistic,
                                                    onTimeout: (context, timespan, task) =>
            {
                Console.WriteLine($"====TimeOut===== : execution timed out after {timespan} seconds.");
            });


            FallbackPolicy <String> fallbackForAnyException = Policy <String>
                                                              .Handle <Exception>()
                                                              .Fallback(
                fallbackAction: () => { Console.WriteLine("999999999"); return("123"); },
                onFallback: e => { Console.WriteLine($"[Polly fallback] : 重試失敗, say goodbye"); }
                );

            CircuitBreakerPolicy circuitPolicy = Policy
                                                 .Handle <Exception>()
                                                 .CircuitBreaker(3, TimeSpan.FromSeconds(0), (ex, ts) =>
            {
                Console.WriteLine($"====CircuitBreaker [OnBreak]=====  ts = {ts.Seconds}s ,ex.message = {ex.Message}");
            }, () =>
            {
                Console.WriteLine("AService OnReset");
            });

            try
            {
                PolicyWrap <String> policyWrap = fallbackForAnyException
                                                 .Wrap(waitAndRetryPolicy)
                                                 .Wrap(circuitPolicy)
                                                 .Wrap(timeoutPolicys);
                policyWrap.Execute(() => doMockHTTPRequest(check));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
        }
Пример #12
0
        public static PolicyWrap DefaultPolicy(int retryAttempts, int timeoutInSec)
        {
            // Set up Polly policy for retries, with increasing timeout between each attempt
            RetryPolicy retryPolicy = Policy.Handle <HttpRequestException>()
                                      .WaitAndRetry(retryAttempts, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

            // Set up Polly timeout policy in case of network being down
            TimeoutPolicy timeOutPolicy = Policy.Timeout(timeoutInSec, TimeoutStrategy.Pessimistic, (context, timeSpan, task) => ManageTimeoutException(context, timeSpan, task));

            // Combine the two policies
            return(Policy.Wrap(retryPolicy, timeOutPolicy));
        }
Пример #13
0
        public FtpTransferOperation(
            OperationOptions oo,
            ILoggerFactory loggerFactory)
        {
            _options = NamedNullException.Assert(oo, nameof(oo));
            var fo = _options.Ftp;

            NamedNullException.Assert(fo, nameof(fo));
            _timeout   = fo.Timeout.HasValue ? fo.Timeout.Value : FtpOptions.MaxFtpTimeout;
            _ftpClient = new SimpleFtpClient(fo.FtpRoot, fo.UserName, fo.Password, _timeout);

            _logger        = NamedNullException.Assert(loggerFactory, nameof(loggerFactory)).CreateLogger <FtpTransferOperation>();
            _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(_timeout), TimeoutStrategy.Pessimistic);
        }
Пример #14
0
        private PolicyWrap BuildProcessEventPolicy()
        {
            //重试策略
            var retryPolicy = RetryPolicy
                              .Handle <Exception>()
                              .WaitAndRetry(_retryCount, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), (ex, time) =>
            {
                _logger.LogInformation($"Process event fails due to \"{ex.InnerException?.Message}\" and  it will re-try after {time.TotalSeconds}s");
            });

            //超时策略
            var timeoutPolicy = TimeoutPolicy.Timeout(30);

            //组合策略
            return(retryPolicy.Wrap(timeoutPolicy));
        }
Пример #15
0
        public CatalogController()
        {
            _timeoutPolicy = Policy.TimeoutAsync(1); // throws TimeoutRejectedException if timeout of 1 second is exceeded

            _httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                .Or <TimeoutRejectedException>()
                .RetryAsync(3);

            _httpRequestFallbackPolicy = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                                         .Or <TimeoutRejectedException>()
                                         .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent(_cachedResult.GetType(), _cachedResult, new JsonMediaTypeFormatter())
            });
        }
Пример #16
0
        public CatalogController()
        {
            _timeoutPolicy = Policy.TimeoutAsync(1, onTimeoutAsync: TimeoutDelegate);

            _httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                .Or <TimeoutRejectedException>()
                .RetryAsync(3, onRetry: HttpRetryPolicyDelegate);

            _httpRequestFallbackPolicy = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                                         .Or <TimeoutRejectedException>()
                                         .FallbackAsync(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new ObjectContent(_cachedResult.GetType(), _cachedResult, new JsonMediaTypeFormatter())
            }, onFallbackAsync: HttpRequestFallbackPolicyDelegate);

            _policyWrap = _httpRequestFallbackPolicy.WrapAsync(_httpRetryPolicy.WrapAsync(_timeoutPolicy));
        }
        /// <summary>
        /// 调用func with timeout,不会抛出异常
        /// </summary>
        /// <param name="func">调用的业务逻辑,func在task中执行(即和调用线程不是一个)</param>
        /// <param name="timeoutSpan">多少时间后过期</param>
        /// <param name="onTimeout">过期后的回调,过期后Polly不会杀死task,task仍然执行</param>
        /// <returns></returns>
        public static PolicyResult <T> RunWithTimeOut <T>(Func <T> func, TimeSpan timeoutSpan, Action <Context, TimeSpan, Task> onTimeout = null)
        {
            //TimeoutStrategy.Pessimistic recognises that there are cases where you need to execute delegates which have no in-built timeout, and do not honor cancellation.Policy使用Task执行user delegate
            //在悲观模式下,Polly不会杀死底层的线程,而是将task传递到onTimeout回调中
            TimeoutPolicy policy = Policy.Timeout(timeoutSpan, TimeoutStrategy.Pessimistic,
                                                  (context, timeSpan, task) =>
            {
                if (onTimeout != null)
                {
                    onTimeout(context, timeSpan, task);
                }
                else
                {
                    //过期后Polly不会杀死task,task仍然执行,需要在这里进行处理
                }
            });

            return(policy.ExecuteAndCapture(func));
        }
        async Task <T> ExecutePostAsync <T>(string requestUri, HttpContent content, bool handlerEncrypted = true) where T : class
        {
            HttpClient client = ConfigureHttpClient(handlerEncrypted);

            TimeSpan timeSpan = _minimunTimeUntilFail;

            if (content is StreamContent)
            {
                timeSpan = _maximunTimeUntilFail;
            }

            CancellationToken cts           = new CancellationTokenSource(timeSpan).Token;
            TimeoutPolicy     timeOutPolicy = Policy.TimeoutAsync(timeSpan);

            using (content)
                using (HttpResponseMessage response = await timeOutPolicy.WrapAsync(_policy).ExecuteAsync(async() => await client.PostAsync(requestUri, content, cts)))
                {
                    return(await ProcessResponse <T>(response));
                }
        }
        public PollyController(IReadOnlyPolicyRegistry <string> policyRegistry)
        {
            #region Configuracao API
            var config = new ConfigurationBuilder()
                         .SetBasePath(Directory.GetCurrentDirectory())
                         .AddJsonFile("appsettings.json")
                         .Build();

            _baseUri = config.GetSection("API:UrlBase").Get <string>();
            #endregion


            #region Policies da Resiliencia
            _policyRegistry = policyRegistry;
            _timeoutPolicy  = Policy.TimeoutAsync(3);

            _httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                .Or <TimeoutRejectedException>()
                .RetryAsync(6);
            #endregion
        }
Пример #20
0
        public ResilientHttpClient(HttpClient client, CircuitBreakerPolicy <HttpResponseMessage> circuitBreakerPolicy)
        {
            _client = client;
            _client.DefaultRequestHeaders.Accept.Clear();
            _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            //circuit breaker policy injected as defined in the Startup class
            _circuitBreakerPolicy = circuitBreakerPolicy;

            //Defining retry policy
            _retryPolicy = Policy.HandleResult <HttpResponseMessage>(x =>
            {
                var result = !x.IsSuccessStatusCode;
                return(result);
            })
                           .Or <TimeoutException>()
                           //Retry 3 times and for each retry wait for 3 seconds
                           .WaitAndRetry(3, sleepDuration => TimeSpan.FromSeconds(3));


            _fallbackCircuitBreakerPolicy = Policy <HttpResponseMessage>
                                            .Handle <BrokenCircuitException>()
                                            .Fallback(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent("Please try again later[Circuit breaker is Open]")
            }
                                                      );


            _fallbackPolicy = Policy.HandleResult <HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
                              .Or <TimeoutRejectedException>()
                              .Fallback(new HttpResponseMessage(HttpStatusCode.OK)
            {
                Content = new StringContent("Some error occured")
            });

            _timeoutPolicy = Policy.Timeout <HttpResponseMessage>(1);
        }
        /// <summary>
        /// Build default circuit breaker, wait and retry and Timeout policy.
        /// </summary>
        /// <param name="transientPolicySettings">retry,timeout and circuit breaker settings.</param>
        /// <returns>policy wrapper.</returns>
        public virtual PolicyWrap <HttpResponseMessage> GetDefaultPolicy(TransientPolicySettings transientPolicySettings)
        {
            //Time out policy to set Http Client request timeout.
            TimeoutPolicy timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromSeconds(transientPolicySettings.HttpTimeOut), timeoutStrategy: TimeoutStrategy.Pessimistic, TimeOutHandler);
            //If http client requiest fails, it will be retried.
            IAsyncPolicy <HttpResponseMessage> retryPolicy = Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode)
                                                             .Or <HttpRequestException>()
                                                             .WaitAndRetryAsync(transientPolicySettings.RetryAttempts, retryafter => TimeSpan.FromSeconds(Math.Pow(2, retryafter) / 2), OnRetry);
            //Circuit breaker to fail fast.
            IAsyncPolicy <HttpResponseMessage> cb = HttpPolicyExtensions
                                                    .HandleTransientHttpError()
                                                    .AdvancedCircuitBreakerAsync(
                transientPolicySettings.CircuitBreakerSettings.FailureThreshold,
                TimeSpan.FromSeconds(transientPolicySettings.CircuitBreakerSettings.SamplingDuration),
                transientPolicySettings.CircuitBreakerSettings.MinimumThroughput,
                TimeSpan.FromSeconds(transientPolicySettings.CircuitBreakerSettings.DurationOfBreak),
                OnBreak,
                OnReset,
                OnHalfOpen);

            //above policies are wrapped.
            return(timeoutPolicy.WrapAsync(retryPolicy.WrapAsync(cb)));
        }
Пример #22
0
        public PollyQoSProvider()
        {
            _timeoutPolicy = Policy.TimeoutAsync(TimeSpan.FromMilliseconds(20000));

            _circuitBreakerPolicy = Policy
                                    .Handle <HttpRequestException>()
                                    .Or <TimeoutRejectedException>()
                                    .Or <TimeoutException>()
                                    .CircuitBreakerAsync(
                exceptionsAllowedBeforeBreaking: 1,
                durationOfBreak: TimeSpan.FromMilliseconds(2000),
                onBreak: (ex, breakDelay) =>
            {
            },
                onReset: () =>
            {
            },
                onHalfOpen: () =>
            {
            }
                );

            _circuitBreaker = new CircuitBreaker(_circuitBreakerPolicy, _timeoutPolicy);
        }
Пример #23
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();
            services.AddApiVersioning(
                o =>
            {
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = new ApiVersion(1, 0);
            });

            var azureStorageSettings        = GetSettings <AzureStorageSettings>();
            var notificationServiceSettings = GetSettings <NotificationServiceSettings>();
            var faultToleranceSettings      = GetSettings <FaultToleranceSettings>();

            services.AddSingleton <IMetricsClient>(context =>
            {
                var metricsClientFactory = new MetricsClientFactory(context.GetRequiredService <ILoggerFactory>(),
                                                                    TimeSpan.FromSeconds(15));
                return(metricsClientFactory.CreateMetricsClient <LoggerMetricsClient>());
            });

            TimeoutPolicy        timeoutPolicy        = Policy.Timeout(faultToleranceSettings.TimeoutLength, TimeoutStrategy.Pessimistic);
            CircuitBreakerPolicy circuitBreakerPolicy = Policy
                                                        .Handle <Exception>()
                                                        .CircuitBreaker(
                exceptionsAllowedBeforeBreaking: faultToleranceSettings.ExceptionsAllowedBeforeBreaking,
                durationOfBreak: TimeSpan.FromMinutes(faultToleranceSettings.DurationOfBreakInMinutes)
                );
            PolicyWrap policyWrap = Policy.Wrap(circuitBreakerPolicy, timeoutPolicy);

            services.AddSingleton <ISyncPolicy>(policyWrap);

            QueueClient queueClient = new QueueClient(notificationServiceSettings.ServiceBusConnectionString,
                                                      notificationServiceSettings.QueueName);
            ServiceBusNotificationServiceClient notificationService = new ServiceBusNotificationServiceClient(queueClient);

            services.AddSingleton <INotificationService>(context =>
                                                         new NotificationServiceMetricsDecorator(
                                                             new NotificationServiceFaultToleranceDecorator(
                                                                 notificationService,
                                                                 context.GetRequiredService <ISyncPolicy>()),
                                                             context.GetRequiredService <IMetricsClient>()));

            AzureCloudTable        profileCloudTable = new AzureCloudTable(azureStorageSettings.ConnectionString, azureStorageSettings.ProfilesTableName);
            AzureTableProfileStore profileStore      = new AzureTableProfileStore(profileCloudTable);

            services.AddSingleton <IProfileStore>(context =>
                                                  new ProfileStoreMetricsDecorator(
                                                      new ProfileStoreFaultToleranceDecorator(
                                                          profileStore,
                                                          context.GetRequiredService <ISyncPolicy>()),
                                                      context.GetRequiredService <IMetricsClient>()));

            AzureCloudTable         messagesCloudTable = new AzureCloudTable(azureStorageSettings.ConnectionString, azureStorageSettings.MessagesTableName);
            AzureTableMessagesStore messagesStore      = new AzureTableMessagesStore(messagesCloudTable);

            services.AddSingleton <IMessagesStore>(context =>
                                                   new MessagesStoreMetricsDecorator(
                                                       new MessagesStoreFaultToleranceDecorator(
                                                           messagesStore,
                                                           context.GetRequiredService <ISyncPolicy>()),
                                                       context.GetRequiredService <IMetricsClient>()));

            AzureCloudTable conversationsCloudTable         = new AzureCloudTable(azureStorageSettings.ConnectionString, azureStorageSettings.UsersTableName);
            AzureTableConversationsStore conversationsStore = new AzureTableConversationsStore(conversationsCloudTable, messagesStore);

            services.AddSingleton <IConversationsStore>(context =>
                                                        new ConversationStoreMetricsDecorator(
                                                            new ConversationsStoreFaultToleranceDecorator(
                                                                conversationsStore,
                                                                context.GetRequiredService <ISyncPolicy>()),
                                                            context.GetRequiredService <IMetricsClient>()));

            services.AddSingleton <IConversationService>(context =>
                                                         new ConversationServiceMetricsDecorator(
                                                             new ConversationService(
                                                                 context.GetRequiredService <IConversationsStore>(),
                                                                 context.GetRequiredService <ILogger <ConversationService> >(),
                                                                 context.GetRequiredService <INotificationService>()),
                                                             context.GetRequiredService <IMetricsClient>()));

            services.AddLogging();
            services.AddMvc();
        }
Пример #24
0
 /// <summary>
 /// Sets the timeout policy.
 /// </summary>
 /// <param name="value">The timeout policy.</param>
 /// <returns></returns>
 public SubscriberBuilder TimeoutAction(TimeoutPolicy value)
 {
     Configuration.TimeoutPolicy = value;
     return(this);
 }
Пример #25
0
        private static void RegisterResilientConsumers(IServiceCollection services)
        {
            const string baseUrl = "http://localhost:5000";
            // Transient errors are: HttpRequestException, 5XX and 408

            var backOffs = new[] { TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(5) };

            Action <DelegateResult <HttpResponseMessage>, TimeSpan, int, Context> onRetry = (result, timeSpan, retryCount, context) =>
            {
                Log.Warning($"Request failed with <{result.Result?.StatusCode}>. Waiting <{timeSpan}> before next retry. Retry attempt <{retryCount}>");
            };

            services.AddHttpClient("5000_exponentialbackoff").ConfigureHttpClient(httpClient => {
                httpClient.BaseAddress = new Uri(baseUrl);
            })
            .AddTransientHttpErrorPolicy(builder =>
            {
                //builder.OrResult(msg => msg.StatusCode == HttpStatusCode.Continue);
                return(builder.WaitAndRetryAsync(backOffs, onRetry));
            });

            services.AddHttpClient("5000_circuitbreaker").ConfigureHttpClient(httpClient => {
                httpClient.BaseAddress = new Uri(baseUrl);
            })
            .AddTransientHttpErrorPolicy(builder =>
            {
                //builder.OrResult(msg => msg.StatusCode == HttpStatusCode.Continue);
                return(builder.CircuitBreakerAsync(2, TimeSpan.FromSeconds(30), (response, timeSpan) => {
                    Log.Information($"Circuit is broken and will remain broken for <{timeSpan}>");
                }, () => {
                    Log.Information("Circuit has been reset");
                }));
            });

            services.AddHttpClient("5000_jitter").ConfigureHttpClient(httpClient => {
                httpClient.BaseAddress = new Uri(baseUrl);
            })
            .AddTransientHttpErrorPolicy(builder =>
            {
                Random jitterer = new Random();
                return(builder.WaitAndRetryAsync(5,
                                                 retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) // exponential back-off: 2, 4, 8 etc
                                                 + TimeSpan.FromMilliseconds(jitterer.Next(0, 1000)),            // plus some jitter: up to 1 second
                                                 onRetry));
            });

            services.AddTransient <BulkheadExecutor>();
            services.AddSingleton(provider => new Func <BulkheadExecutor>(() => provider.GetService <BulkheadExecutor>()));

            services.AddHttpClient("5000_bulkhead").ConfigureHttpClient(httpClient => {
                httpClient.BaseAddress = new Uri(baseUrl);
            });

            services.AddHttpClient("5000_fallback").ConfigureHttpClient(httpClient => {
                httpClient.BaseAddress = new Uri(baseUrl);
            })
            .AddTransientHttpErrorPolicy(builder =>
            {
                return(builder.FallbackAsync(new HttpResponseMessage
                {
                    Content = new StringContent("Fallback value returned")
                }, result =>
                {
                    Log.Error($"Fallback value substituted, due to: {result.Exception}.");
                    return Task.CompletedTask;
                }));
            });

            services.AddHttpClient("5000_cache").ConfigureHttpClient(httpClient => {
                httpClient.BaseAddress = new Uri(baseUrl);
            });

            services.AddHttpClient("5000_timeout").ConfigureHttpClient(httpClient => {
                httpClient.BaseAddress = new Uri(baseUrl);
            });

            services.AddSingleton <PolicyRegistryExecutor>();
            services.AddMemoryCache();
            services.AddSingleton <IAsyncCacheProvider, MemoryCacheProvider>();

            CachePolicy <HttpResponseMessage> cachePolicy = Policy.CacheAsync <HttpResponseMessage>(services.BuildServiceProvider().GetRequiredService <IAsyncCacheProvider>(), TimeSpan.FromMinutes(1),
                                                                                                    (context, value) => Log.Information("OnCacheGet"),
                                                                                                    (context, value) => Log.Information("OnCacheMiss"),
                                                                                                    (context, value) => Log.Information("OnCachePut"),
                                                                                                    (context, value, exception) => Log.Information("OnCacheGetError"),
                                                                                                    (context, value, exception) => Log.Information("OnCachePutError"));

            //TimeoutPolicy<HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(2).Seconds, TimeoutStrategy.Optimistic, (context, t, executedTask) =>
            //{
            //    Log.Information("Timeout occurred");
            //    return Task.CompletedTask;
            //});

            TimeoutPolicy <HttpResponseMessage> timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(2).Seconds, TimeoutStrategy.Pessimistic, (context, t, executedTask) =>
            {
                Log.Information("Timeout occurred");
                return(Task.CompletedTask);
            });

            services.AddSingleton <IPolicyRegistry <string>, PolicyRegistry>(serviceProvider =>
            {
                PolicyRegistry registry = new PolicyRegistry();
                registry.Add("cachePolicy", cachePolicy);
                registry.Add("timeoutPolicy", timeoutPolicy);
                return(registry);
            });
        }
Пример #26
0
        private async Task <BigInteger> IndexBlocksAsync(string indexerId, BigInteger currentBlockNumber,
                                                         Func <BigInteger, bool> checkDelegate)
        {
            try
            {
                if (_firstRun && _indexingSettings.From == currentBlockNumber)
                {
                    await _logger.WriteInfoAsync
                    (
                        "BlockIndexingJob",
                        "IndexBlocksAsync",
                        indexerId,
                        $"Indexing begins from block-{currentBlockNumber}",
                        DateTime.UtcNow
                    );

                    var blockContent = await _rpcBlockReader.ReadBlockAsync(currentBlockNumber);

                    var blockContext = new BlockContext(Id, Version, indexerId, blockContent);

                    await _indexingService.IndexBlockAsync(blockContext);

                    currentBlockNumber++;

                    _firstRun = false;
                }

                var iterationVector = 0;

                while (checkDelegate(currentBlockNumber))
                {
                    BlockContent blockContent = null;

                    var transactionCount = 0;

                    await _logger.WriteInfoAsync
                    (
                        "BlockIndexingJob",
                        "IndexBlocksAsync",
                        indexerId,
                        $"Indexing block-{currentBlockNumber}, Vector:{iterationVector}",
                        DateTime.UtcNow
                    );

                    //Would throw on time out
                    await RetryPolicy.ExecuteAsync(async() =>
                    {
                        await _logger.WriteInfoAsync
                        (
                            "BlockIndexingJob",
                            "IndexBlocksAsync",
                            indexerId,
                            $"Block-{currentBlockNumber}, Vector:{iterationVector} Reading info",
                            DateTime.UtcNow
                        );

                        //Throws Timeout Exception
                        await TimeoutPolicy.ExecuteAsync(async() =>
                        {
                            blockContent = blockContent ?? await _rpcBlockReader.ReadBlockAsync(currentBlockNumber);
                        }, TimeSpan.FromMinutes(7));

                        await _logger.WriteInfoAsync
                        (
                            "BlockIndexingJob",
                            "IndexBlocksAsync",
                            indexerId,
                            $"Checking existence of the parent-{currentBlockNumber}",
                            DateTime.UtcNow
                        );

                        var blockContext = new BlockContext(Id, Version, indexerId, blockContent);
                        var blockExists  = await _blockService.DoesBlockExist(blockContent.BlockModel.ParentHash);

                        transactionCount = blockContent.Transactions.Count;
                        iterationVector  = blockExists ? 1 : -1; //That is how we deal with forks

                        await _logger.WriteInfoAsync
                        (
                            "BlockIndexingJob",
                            "IndexBlocksAsync",
                            indexerId,
                            $"Indexing block in DB -{currentBlockNumber}",
                            DateTime.UtcNow
                        );

                        // Throws Timeout Exception
                        await TimeoutPolicy.ExecuteAsync(async() =>
                        {
                            await _indexingService.IndexBlockAsync(blockContext);
                        }, TimeSpan.FromMinutes(5));
                    }, 5, 100);

                    await _logger.WriteInfoAsync
                    (
                        "BlockIndexingJob",
                        "IndexBlocksAsync",
                        indexerId,
                        $"Indexing completed for block-{currentBlockNumber}, Vector:{iterationVector}, transaction count - {transactionCount}",
                        DateTime.UtcNow
                    );

                    currentBlockNumber += iterationVector;
                }
            }
            catch (Exception e)
            {
                if (e is BlockIsNotYetMinedException)
                {
                    throw;
                }

                await _logger.WriteErrorAsync
                (
                    "BlockIndexingJob",
                    "RunAsync",
                    $"Indexing failed for block-{currentBlockNumber}",
                    e,
                    DateTime.UtcNow
                );

                throw;
            }

            return(currentBlockNumber);
        }
Пример #27
0
        public void CombinePolicyConfigsTest()
        {
            var           type       = typeof(PolicyFactory);
            PolicyFactory factory    = new PolicyFactory();
            string        methodName = "CombinePolicyConfigs";

            var configs = (List <IPolicyConfig>)Helper.RunInstanceMethod(type, methodName, factory, new object[3] {
                null, null, null
            });

            Assert.Empty(configs);

            var factoryPolicies = new List <IPolicyConfig>()
            {
            };
            var apiPolicies = new List <IPolicyConfig>()
            {
            };
            var sortIndexs = new List <int>();

            var configs2 = (List <IPolicyConfig>)Helper.RunInstanceMethod(type, methodName, factory, new object[3] {
                factoryPolicies, apiPolicies, sortIndexs
            });

            Assert.Empty(configs2);

            RetryPolicy retryPolicy = new RetryPolicy(5);

            factoryPolicies.Add(retryPolicy);
            var configs3 = (List <IPolicyConfig>)Helper.RunInstanceMethod(type, methodName, factory, new object[3] {
                factoryPolicies, apiPolicies, sortIndexs
            });

            Assert.NotEmpty(configs3);
            Assert.Single(configs3);

            TimeoutPolicy timeoutPolicy = new TimeoutPolicy(300);

            apiPolicies.Add(timeoutPolicy);
            var configs4 = (List <IPolicyConfig>)Helper.RunInstanceMethod(type, methodName, factory, new object[3] {
                factoryPolicies, apiPolicies, sortIndexs
            });

            Assert.NotEmpty(configs4);
            Assert.Equal(2, configs4.Count);
            Assert.Equal(retryPolicy, configs4[0]);

            RetryPolicy apiRetryPolicy = new RetryPolicy(8);

            apiPolicies.Add(apiRetryPolicy);
            var configs5 = (List <IPolicyConfig>)Helper.RunInstanceMethod(type, methodName, factory, new object[3] {
                factoryPolicies, apiPolicies, sortIndexs
            });

            Assert.Equal(2, configs5.Count);
            Assert.Equal(apiRetryPolicy, configs5[0]);

            sortIndexs = new List <int>()
            {
                5, 4, 3, 2, 1
            };
            var configs6 = (List <IPolicyConfig>)Helper.RunInstanceMethod(type, methodName, factory, new object[3] {
                factoryPolicies, apiPolicies, sortIndexs
            });

            Assert.NotEmpty(configs6);
            Assert.Equal(timeoutPolicy, configs6[0]);
        }
Пример #28
0
 public CircuitBreaker(CircuitBreakerPolicy circuitBreakerPolicy, TimeoutPolicy timeoutPolicy)
 {
     CircuitBreakerPolicy = circuitBreakerPolicy;
     TimeoutPolicy        = timeoutPolicy;
 }