public static IAsyncPolicy <HttpResponseMessage> Basic(int allowedUnsuccessfulCalls, int durationOfBreakInSeconds) =>
 HttpPolicyExtensions.HandleTransientHttpError()
 .Or <TaskCanceledException>()
 .Or <TimeoutException>()
 .CircuitBreakerAsync(allowedUnsuccessfulCalls, TimeSpan.FromSeconds(durationOfBreakInSeconds),
                      (result, breakDuration) => throw new BrokenCircuitException("Service inoperative. Circuit is open"),
示例#2
0
文件: Startup.cs 项目: overbit/janus
 private static IAsyncPolicy <HttpResponseMessage> GetBankApiRetryPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
 }
示例#3
0
 private IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy()
 {
     return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(3, TimeSpan.FromSeconds(30)));
 }
示例#4
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            var cosmosConfig = new CosmosConfig(
                _settings.CosmosSettings.DatabaseName,
                _settings.CosmosSettings.EndpointUri,
                _settings.CosmosSettings.PrimaryKey,
                _settings.CosmosSettings.RequestTimeoutInSeconds
                );
            var cosmosContainers = new List <ContainerInfo>()
            {
                new ContainerInfo()
                {
                    Name         = "rmas",
                    PartitionKey = "PartitionKey"
                }
            };

            var avalaraConfig = new AvalaraConfig()
            {
                BaseApiUrl  = _settings.AvalaraSettings.BaseApiUrl,
                AccountID   = _settings.AvalaraSettings.AccountID,
                LicenseKey  = _settings.AvalaraSettings.LicenseKey,
                CompanyCode = _settings.AvalaraSettings.CompanyCode,
                CompanyID   = _settings.AvalaraSettings.CompanyID
            };

            var currencyConfig = new BlobServiceConfig()
            {
                ConnectionString = _settings.BlobSettings.ConnectionString,
                Container        = _settings.BlobSettings.ContainerNameExchangeRates
            };
            var middlewareErrorsConfig = new BlobServiceConfig()
            {
                ConnectionString = _settings.BlobSettings.ConnectionString,
                Container        = "unhandled-errors-log"
            };
            var assetConfig = new BlobServiceConfig()
            {
                ConnectionString = _settings.BlobSettings.ConnectionString,
                Container        = "assets",
                AccessType       = BlobContainerPublicAccessType.Container
            };

            var flurlClientFactory    = new PerBaseUrlFlurlClientFactory();
            var smartyStreetsUsClient = new ClientBuilder(_settings.SmartyStreetSettings.AuthID, _settings.SmartyStreetSettings.AuthToken).BuildUsStreetApiClient();

            services
            .Configure <KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            })
            .Configure <IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            })
            .AddSingleton <ISimpleCache, OrderCloud.Common.Services.LazyCacheService>()    // Replace LazyCacheService with RedisService if you have multiple server instances.
            .ConfigureServices()
            .AddOrderCloudUserAuth()
            .AddOrderCloudWebhookAuth(opts => opts.HashKey = _settings.OrderCloudSettings.WebhookHashKey)
            .InjectCosmosStore <LogQuery, OrchestrationLog>(cosmosConfig)
            .InjectCosmosStore <ReportTemplateQuery, ReportTemplate>(cosmosConfig)
            .AddCosmosDb(_settings.CosmosSettings.EndpointUri, _settings.CosmosSettings.PrimaryKey, _settings.CosmosSettings.DatabaseName, cosmosContainers)
            .Inject <IPortalService>()
            .Inject <ISmartyStreetsCommand>()
            .Inject <ICheckoutIntegrationCommand>()
            .Inject <IShipmentCommand>()
            .Inject <IOrderCommand>()
            .Inject <IPaymentCommand>()
            .Inject <IOrderSubmitCommand>()
            .Inject <IEnvironmentSeedCommand>()
            .Inject <IHSProductCommand>()
            .Inject <ILineItemCommand>()
            .Inject <IMeProductCommand>()
            .Inject <IHSCatalogCommand>()
            .Inject <ISendgridService>()
            .Inject <IHSSupplierCommand>()
            .Inject <ICreditCardCommand>()
            .Inject <ISupportAlertService>()
            .Inject <IOrderCalcService>()
            .Inject <IUserContextProvider>()
            .Inject <ISupplierApiClientHelper>()
            .AddSingleton <ISendGridClient>(x => new SendGridClient(_settings.SendgridSettings.ApiKey))
            .AddSingleton <IFlurlClientFactory>(x => flurlClientFactory)
            .AddSingleton <DownloadReportCommand>()
            .Inject <IRMARepo>()
            .Inject <IZohoClient>()
            .AddSingleton <IZohoCommand>(z => new ZohoCommand(new ZohoClient(
                                                                  new ZohoClientConfig()
            {
                ApiUrl         = "https://books.zoho.com/api/v3",
                AccessToken    = _settings.ZohoSettings.AccessToken,
                ClientId       = _settings.ZohoSettings.ClientId,
                ClientSecret   = _settings.ZohoSettings.ClientSecret,
                OrganizationID = _settings.ZohoSettings.OrgID
            }, flurlClientFactory),
                                                              new OrderCloudClient(new OrderCloudClientConfig
            {
                ApiUrl       = _settings.OrderCloudSettings.ApiUrl,
                AuthUrl      = _settings.OrderCloudSettings.ApiUrl,
                ClientId     = _settings.OrderCloudSettings.MiddlewareClientID,
                ClientSecret = _settings.OrderCloudSettings.MiddlewareClientSecret,
                Roles        = new[] { ApiRole.FullAccess }
            })))
            .AddSingleton <IOrderCloudIntegrationsExchangeRatesClient, OrderCloudIntegrationsExchangeRatesClient>()
            .AddSingleton <IAssetClient>(provider => new AssetClient(new OrderCloudIntegrationsBlobService(assetConfig), _settings))
            .AddSingleton <IExchangeRatesCommand>(provider => new ExchangeRatesCommand(new OrderCloudIntegrationsBlobService(currencyConfig), flurlClientFactory, provider.GetService <ISimpleCache>()))
            .AddSingleton <IAvalaraCommand>(x => new AvalaraCommand(
                                                avalaraConfig,
                                                new AvaTaxClient("four51_headstart", "v1", "four51_headstart", new Uri(avalaraConfig.BaseApiUrl)
                                                                 ).WithSecurity(_settings.AvalaraSettings.AccountID, _settings.AvalaraSettings.LicenseKey)))
            .AddSingleton <IEasyPostShippingService>(x => new EasyPostShippingService(new EasyPostConfig()
            {
                APIKey = _settings.EasyPostSettings.APIKey
            }))
            .AddSingleton <ISmartyStreetsService>(x => new SmartyStreetsService(_settings.SmartyStreetSettings, smartyStreetsUsClient))
            .AddSingleton <IOrderCloudIntegrationsCardConnectService>(x => new OrderCloudIntegrationsCardConnectService(_settings.CardConnectSettings, flurlClientFactory))
            .AddSingleton <IOrderCloudClient>(provider => new OrderCloudClient(new OrderCloudClientConfig
            {
                ApiUrl       = _settings.OrderCloudSettings.ApiUrl,
                AuthUrl      = _settings.OrderCloudSettings.ApiUrl,
                ClientId     = _settings.OrderCloudSettings.MiddlewareClientID,
                ClientSecret = _settings.OrderCloudSettings.MiddlewareClientSecret,
                Roles        = new[]
                {
                    ApiRole.FullAccess
                }
            }))
            .AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "Headstart API", Version = "v1"
                });
                c.CustomSchemaIds(x => x.FullName);
            });
            var serviceProvider = services.BuildServiceProvider();

            services
            .AddApplicationInsightsTelemetry(new ApplicationInsightsServiceOptions
            {
                EnableAdaptiveSampling = false,     // retain all data
                InstrumentationKey     = _settings.ApplicationInsightsSettings.InstrumentationKey
            });


            ServicePointManager.DefaultConnectionLimit       = int.MaxValue;
            FlurlHttp.Configure(settings => settings.Timeout = TimeSpan.FromSeconds(_settings.FlurlSettings.TimeoutInSeconds == 0 ? 30 : _settings.FlurlSettings.TimeoutInSeconds));

            // This adds retry logic for any api call that fails with a transient error (server errors, timeouts, or rate limiting requests)
            // Will retry up to 3 times using exponential backoff and jitter, a mean of 3 seconds wait time in between retries
            // https://github.com/App-vNext/Polly/wiki/Retry-with-jitter#more-complex-jitter
            var delay  = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(3), retryCount: 3);
            var policy = HttpPolicyExtensions
                         .HandleTransientHttpError()
                         .OrResult(response => response.StatusCode == HttpStatusCode.TooManyRequests)
                         .WaitAndRetryAsync(delay);

            FlurlHttp.Configure(settings => settings.HttpClientFactory = new PollyFactory(policy));
        }
示例#5
0
 private static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 => HttpPolicyExtensions
 .HandleTransientHttpError()
 .WaitAndRetryAsync(5, attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)));
 static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromMilliseconds(Math.Pow(200, retryAttempt))));
 }
示例#7
0
 private IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions.HandleTransientHttpError().OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
            .WaitAndRetryAsync(retryCount: 5, sleepDurationProvider: retryAttemp => TimeSpan.FromSeconds(Math.Pow(2, retryAttemp))));
 }
示例#8
0
 public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy() => HttpPolicyExtensions
 .HandleTransientHttpError()
 .CircuitBreakerAsync(2, TimeSpan.FromSeconds(30));
示例#9
0
        /// <summary>
        /// Initializes <see cref="IHost"/> with Sentry monitoring.
        /// </summary>
        public static IHost Init(Context context, string dsn)
        {
            SentrySdk.Init(context, o =>
            {
                // TODO: ShouldCan be deleted once this PR is released: https://github.com/getsentry/sentry-dotnet/pull/1750/files#diff-c55d438dd1d5f3731c0d04d0f1213af4873645b1daa44c4c6e1b24192110d8f8R166-R167
                // System.UnauthorizedAccessException: Access to the path '/proc/stat' is denied.
                o.DetectStartupTime = StartupTimeDetectionMode.Fast;
#if ANDROID
                // TODO: Should be added OOTB
                o.Release = $"{AppInfo.PackageName}@{AppInfo.VersionString}+{AppInfo.BuildString}";

                o.Android.AttachScreenshot        = true;
                o.Android.ProfilingEnabled        = true;
                o.Android.EnableAndroidSdkTracing = true; // Will double report transactions but to get profiler data
#endif
                o.TracesSampleRate = 1.0;
                o.Debug            = true;
#if DEBUG
                o.Environment = "development";
#else
                o.DiagnosticLevel = SentryLevel.Info;
#endif
                o.MaxBreadcrumbs        = 250;
                o.InitCacheFlushTimeout = TimeSpan.FromSeconds(5);
                o.AttachStacktrace      = true;
                o.Dsn            = dsn;
                o.SendDefaultPii = true;

                // TODO: This needs to be built-in
                o.BeforeSend += @event =>
                {
                    const string traceIdKey = "TraceIdentifier";
                    switch (@event.Exception)
                    {
                    case OperationCanceledException _:
                        return(null);

                    case var e when e?.Data.Contains(traceIdKey) == true:
                        @event.SetTag(traceIdKey, e.Data[traceIdKey]?.ToString() ?? "unknown");
                        break;
                    }

                    return(@event);
                };
                // TODO: https://github.com/getsentry/sentry-dotnet/issues/1751
                // o.BeforeBreadcrumb = breadcrumb
                //     // This logger adds 3 crumbs for each HTTP request and we already have a Sentry integration for HTTP
                //     // Which shows the right category, status code and a link
                //     => string.Equals(breadcrumb.Category, "System.Net.Http.HttpClient.ISymbolClient.LogicalHandler")
                //        || string.Equals(breadcrumb.Category, "System.Net.Http.HttpClient.ISymbolClient.ClientHandler")
                //         ? null
                //         : breadcrumb;
            });

            var tran = SentrySdk.StartTransaction("AppStart", "activity.load");

            SentrySdk.ConfigureScope(s =>
            {
                s.Transaction = tran;
                s.AddAttachment(new ScreenshotAttachment());
            });

            // TODO: Where is this span?
            var iocSpan   = tran.StartChild("container.init", "Initializing the IoC container");
            var userAgent = Java.Lang.JavaSystem.GetProperty("http.agent") ?? "Android/" + typeof(Host).Assembly.GetName().Version;
            var host      = Startup.Init(services =>
            {
                var messages = new []
                {
                    // Unable to resolve host "symbol-collector.services.sentry.io": No address associated with hostname
                    "No address associated with hostname",
                    // Read error: ssl=0x79ea0d6988: SSL_ERROR_WANT_READ occurred. You should never see this.
                    "You should never see this",
                    // handshake error: ssl=0x78f5b01b48: I/O error during system call, Try again
                    "Try again",
                    // failed to connect to symbol-collector.services.sentry.io/35.188.18.176 (port 443) from /10.22.91.71 (port 43860) after 86400000ms: isConnected failed: ETIMEDOUT (Connection timed out)
                    "Connection timed out",
                    // Read error: ssl=0x77f787e308: Failure in SSL library, usually a protocol error
                    // error:100003fc:SSL routines:OPENSSL_internal:SSLV3_ALERT_BAD_RECORD_MAC (external/boringssl/src/ssl/tls_record.cc:592 0x77f854d8c8:0x00000001)
                    "Failure in SSL library, usually a protocol error",
                };
                services.AddSingleton <AndroidMessageHandler>();
                services.AddHttpClient <ISymbolClient, SymbolClient>()
                .ConfigurePrimaryHttpMessageHandler <AndroidMessageHandler>()
                .AddPolicyHandler((s, r) =>
                                  HttpPolicyExtensions.HandleTransientHttpError()
                                  // Could be deleted if merged: https://github.com/App-vNext/Polly.Extensions.Http/pull/33
                                  // On Android web get WebException instead of HttpResponseMessage which HandleTransientHttpError covers
                                  .Or <IOException>(e => messages.Any(m => e.Message.Contains(m)))
                                  .Or <WebException>(e => messages.Any(m => e.Message.Contains(m)))
                                  .Or <SocketTimeoutException>()
                                  .SentryPolicy(s));

                services.AddSingleton <AndroidUploader>();
                services.AddOptions().Configure <SymbolClientOptions>(o =>
                {
                    o.UserAgent = userAgent;
                    o.BlockListedPaths.Add("/system/etc/.booking.data.aid");
                    o.BlockListedPaths.Add("/system/build.prop");
                    o.BlockListedPaths.Add("/system/vendor/bin/netstat");
                    o.BlockListedPaths.Add("/system/vendor/bin/swapoff");
                });
                services.AddOptions().Configure <ObjectFileParserOptions>(o =>
                {
                    o.IncludeHash = false;
                    o.UseFallbackObjectFileParser = false; // Android only, use only ELF parser.
                });
            });
            iocSpan.Finish();

            SentrySdk.ConfigureScope(s => s.SetTag("user-agent", userAgent));
            return(host);
        }
示例#10
0
        internal HttpClientFactoryConfigurator(ILogger logger)
        {
            var retryPolicy = HttpPolicyExtensions
                              .HandleTransientHttpError()
                              .Or <TimeoutRejectedException>() // thrown by Polly's TimeoutPolicy if the inner call times out
                              .WaitAndRetryAsync(new[]
            {
                TimeSpan.FromSeconds(1),
                TimeSpan.FromSeconds(5),
                TimeSpan.FromSeconds(10)
            },
                                                 onRetry: (r, ts, n, ctx) =>
            {
                if (r.Result == default)     // no result, an exception was thrown
                {
                    logger.LogError(r.Exception, $"Retry[{n}]: {r.Exception.Message}");
                }
                else
                {
                    logger.LogError($"Retry[{n}]: ({r.Result.StatusCode}) {r.Result.ReasonPhrase}");
                }
            });

            var timeoutPolicy = Policy.TimeoutAsync <HttpResponseMessage>(20); // Timeout for an individual try

            var circuitBreakerPolicy = HttpPolicyExtensions
                                       .HandleTransientHttpError()
                                       .CircuitBreakerAsync(
                handledEventsAllowedBeforeBreaking: 3,
                durationOfBreak: TimeSpan.FromSeconds(30),
                onBreak: (r, ts, ctx) =>
            {
                if (r.Result == default)         // no result, an exception was thrown
                {
                    logger.LogError(r.Exception, $"Circuit Breaking: {r.Exception.Message}");
                }
                else
                {
                    logger.LogError($"Circuit Breaking: ({r.Result.StatusCode}) {r.Result.ReasonPhrase}");
                }
            },
                onReset: ctx =>
            {
                logger.LogWarning($"Circuit Resetting...");
            });


            ServiceProvider = new ServiceCollection()

                              .AddHttpClient("snapshot", client =>
            {
                //client.Timeout = Timeout.InfiniteTimeSpan; // default: 100 seconds
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                //client.DefaultRequestVersion = new Version(2, 0);
            })
                              .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
            {
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                AllowAutoRedirect      = false,
                //MaxConnectionsPerServer = 1 // The default: int.MaxValue
            })
                              //.SetHandlerLifetime(Timeout.InfiniteTimeSpan) // default: 2 minutes
                              .AddPolicyHandler(retryPolicy)
                              .AddPolicyHandler(timeoutPolicy)
                              .AddPolicyHandler(circuitBreakerPolicy)
                              .Services

                              .AddHttpClient("history", client =>
            {
                //client.Timeout = Timeout.InfiniteTimeSpan; // default: 100 seconds
                client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
            })
                              .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler()
            {
                AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
                AllowAutoRedirect      = false,
                CookieContainer        = new CookieContainer(),
                //MaxConnectionsPerServer = 1 // The default: int.MaxValue
            })
                              //.SetHandlerLifetime(Timeout.InfiniteTimeSpan) // default: 2 minutes
                              .AddPolicyHandler(retryPolicy)
                              .AddPolicyHandler(timeoutPolicy)
                              .AddPolicyHandler(circuitBreakerPolicy)
                              .Services

                              .BuildServiceProvider();
        }
示例#11
0
 public static IAsyncPolicy <HttpResponseMessage> GetWaitAndRetryForeverPolicy() => HttpPolicyExtensions
 .HandleTransientHttpError()
 .WaitAndRetryForeverAsync(retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
 private static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(retryCount: 6, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
 }
示例#13
0
 /// <summary>
 /// Policy to break the retry policy after getting same error for 2 times consecutively
 /// </summary>
 /// <returns></returns>
 public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy() =>
 HttpPolicyExtensions
 .HandleTransientHttpError()                                             // Only handle 408 or 5xx errors
 .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.Forbidden) // Configure for additional failures
 .CircuitBreakerAsync(2, TimeSpan.FromSeconds(6));
示例#14
0
        public static void RegisterServices(IServiceCollection services, IHostingEnvironment environment, IConfiguration configuration)
        {
            IdentityModelEventSource.ShowPII = true;

            //Application
            services.AddScoped <IUserService, UserService>();
            services.AddScoped <IUserQueryService, UserQueryService>();
            services.AddScoped <IUserPreferenceService, UserPreferenceService>();
            services.AddScoped <IUserActivityService, UserActivityService>();
            services.AddScoped <IUserActivityQueryService, UserActivityQueryService>();
            services.AddScoped <ICustomerService, CustomerService>();
            services.AddScoped <ICustomerMemberService, CustomerMemberService>();
            services.AddScoped <ICustomerQueryService, CustomerQueryService>();

            services.AddScoped <IIdentityService, IdentityService>();

            services.AddDbContext <CoreAuthDbContext>(options =>
                                                      options.UseLazyLoadingProxies()
                                                      .UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                                                                    sqlServerOptionsAction: sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(
                    maxRetryCount: 10,
                    maxRetryDelay: TimeSpan.FromSeconds(30),
                    errorNumbersToAdd: null);
            })
                                                      );

            services.AddIdentity <User, IdentityRole>(o =>
            {
                // SignIn settings
                // o.SignIn.RequireConfirmedEmail = true;

                // User settings
                o.User.RequireUniqueEmail = true;

                // Password settings
                o.Password.RequireDigit           = true;
                o.Password.RequireLowercase       = true;
                o.Password.RequireUppercase       = true;
                o.Password.RequireNonAlphanumeric = true;
                o.Password.RequiredLength         = 8;
            })
            .AddEntityFrameworkStores <CoreAuthDbContext>()
            .AddDefaultTokenProviders();

            services.ConfigureApplicationCookie(options =>
            {
                options.LoginPath        = $"/Identity/Account/Login";
                options.LogoutPath       = $"/Identity/Account/Logout";
                options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
            });

            var migrationsAssembly = typeof(CoreAuthDbContext).GetTypeInfo().Assembly.GetName().Name;

            services.AddIdentityServer(options =>
            {
                options.UserInteraction.LoginUrl  = "/Identity/Account/Login";
                options.UserInteraction.LogoutUrl = "/Identity/Account/Logout";

                options.Events.RaiseSuccessEvents = true;
                options.Events.RaiseFailureEvents = true;
                options.Events.RaiseErrorEvents   = true;
            })
            .AddDeveloperSigningCredential()
            .AddAspNetIdentity <User>()
            .AddConfigurationStore(options =>
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                                                                  sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    sqlOptions.EnableRetryOnFailure(
                        maxRetryCount: 10,
                        maxRetryDelay: TimeSpan.FromSeconds(30),
                        errorNumbersToAdd: null);
                });
            })
            .AddOperationalStore(options =>
            {
                options.ConfigureDbContext = builder =>
                                             builder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
                                                                  sqlServerOptionsAction: sqlOptions =>
                {
                    sqlOptions.MigrationsAssembly(migrationsAssembly);
                    sqlOptions.EnableRetryOnFailure(
                        maxRetryCount: 10,
                        maxRetryDelay: TimeSpan.FromSeconds(30),
                        errorNumbersToAdd: null);
                });
                // this enables automatic token cleanup. this is optional.
                options.EnableTokenCleanup   = true;
                options.TokenCleanupInterval = 30;
            });

            services.AddHttpContextAccessor();
            services.AddHttpClient();

            // Domain
            services.AddScoped <IDomainManagerService, DomainManagerService>();

            // Infra - Data
            services.AddTransient <IUserRepository, UserSqlServerRepository>();
            services.AddTransient <ICustomerRepository, CustomerSqlServerRepository>();
            services.AddTransient <ICustomerMemberRepository, CustomerMemberSqlServerRepository>();


            //Polly Policies
            IPolicyRegistry <string> registry = services.AddPolicyRegistry();

            IAsyncPolicy <HttpResponseMessage> httpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode && r.StatusCode != System.Net.HttpStatusCode.Conflict)
                .RetryAsync(3);

            registry.Add("SimpleHttpRetryPolicy", httpRetryPolicy);

            Random jitterer = new Random();

            IAsyncPolicy <HttpResponseMessage> httWaitAndpRetryPolicy =
                Policy.HandleResult <HttpResponseMessage>(r => !r.IsSuccessStatusCode && r.StatusCode != System.Net.HttpStatusCode.Conflict)
                .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
                                   + TimeSpan.FromMilliseconds(jitterer.Next(0, 100)));

            registry.Add("SimpleWaitAndRetryPolicy", httWaitAndpRetryPolicy);

            IAsyncPolicy <HttpResponseMessage> noOpPolicy = Policy.NoOpAsync()
                                                            .AsAsyncPolicy <HttpResponseMessage>();

            registry.Add("NoOpPolicy", noOpPolicy);

            services.AddHttpClient("RemoteServerFromService", client =>
            {
                client.DefaultRequestHeaders.Add("Accept", "application/json");
            })
            .AddPolicyHandlerFromRegistry((policyRegistry, httpRequestMessage) =>
            {
                if (httpRequestMessage.Method == HttpMethod.Get)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleHttpRetryPolicy"));
                }
                else if (httpRequestMessage.Method == HttpMethod.Post)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("NoOpPolicy"));
                }
                else
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleWaitAndRetryPolicy"));
                }
            })
            .AddPolicyHandler((httpRequestMessage) => {
                return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
            });

            services.AddHttpClient("RemoteServerFromWorker", client =>
            {
                client.DefaultRequestHeaders.Add("Accept", "application/json");
            })
            .AddPolicyHandlerFromRegistry((policyRegistry, httpRequestMessage) =>
            {
                if (httpRequestMessage.Method == HttpMethod.Get)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleHttpRetryPolicy"));
                }
                else if (httpRequestMessage.Method == HttpMethod.Post)
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("NoOpPolicy"));
                }
                else
                {
                    return(policyRegistry.Get <IAsyncPolicy <HttpResponseMessage> >("SimpleWaitAndRetryPolicy"));
                }
            })
            .AddPolicyHandler((httpRequestMessage) => {
                return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
            });
        }
示例#15
0
 private IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPattern()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(handledEventsAllowedBeforeBreaking: 3, TimeSpan.FromSeconds(30)));
 }
示例#16
0
 private static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(2, TimeSpan.FromSeconds(30))); //After two times falls it will not retry until 30 sec.
 }
示例#17
0
 private static Polly.Retry.AsyncRetryPolicy <HttpResponseMessage> RetryPolicy(int retries)
 => HttpPolicyExtensions
 .HandleTransientHttpError()
 .Or <TimeoutRejectedException>()
 .RetryAsync(retries);
示例#18
0
        public async Task <DeveloperApiKeyResult> GetApiKeyOrNullAsync(bool invalidateCache = false)
        {
            if (!AuthService.IsLoggedIn())
            {
                return(null);
            }

            if (invalidateCache)
            {
                _apiKeyResult = null;
            }

            if (_apiKeyResult != null)
            {
                return(_apiKeyResult);
            }

            var url = $"{CliUrls.WwwAbpIo}api/license/api-key";

            using (var client = new CliHttpClient())
            {
                var response = await HttpPolicyExtensions
                               .HandleTransientHttpError()
                               .OrResult(msg => !msg.IsSuccessStatusCode)
                               .WaitAndRetryAsync(new[]
                {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(3),
                    TimeSpan.FromSeconds(7)
                },
                                                  (responseMessage, timeSpan, retryCount, context) =>
                {
                    if (responseMessage.Exception != null)
                    {
                        _logger.LogWarning(
                            $"{retryCount}. request attempt failed to {url} with an error: \"{responseMessage.Exception.Message}\". " +
                            $"Waiting {timeSpan.TotalSeconds} secs for the next try...");
                    }
                    else if (responseMessage.Result != null)
                    {
                        _logger.LogWarning(
                            $"{retryCount}. request attempt failed {url} with {(int)responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
                            $"Waiting {timeSpan.TotalSeconds} secs for the next try...");
                    }
                })
                               .ExecuteAsync(async() => await client.GetAsync(url).ConfigureAwait(false)).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                {
                    throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'");
                }

                await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response).ConfigureAwait(false);

                var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                var apiKeyResult = JsonSerializer.Deserialize <DeveloperApiKeyResult>(responseContent);

                return(apiKeyResult);
            }
        }
示例#19
0
        static async Task RunWithRetey()
        {
            var services = new ServiceCollection();

            var dict = new Dictionary <string, string>();

            dict.Add("RetryCount", "5");
            dict.Add("RetryInterval", "1000");
            var configuration = new ConfigurationBuilder().AddInMemoryCollection(dict).Build();

            services.AddTransient <IConfiguration>(sp => configuration);
            services.Configure <RetryOptions>(opt =>
            {
                opt.RetryCount    = int.Parse(configuration["RetryCount"]);
                opt.RetryInterval = int.Parse(configuration["RetryInterval"]);
            });

            services.AddGrpcClient <Greeter.GreeterClient>(opt =>
            {
                opt.Address = new Uri("https://localhost:8001");
            })
            .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
            {
                ClientCertificateOptions = ClientCertificateOption.Manual,
                ServerCertificateCustomValidationCallback = (httpRequestMessage, cert, cetChain, policyErrors) => true
            })
            .AddPolicyHandler(
                HttpPolicyExtensions.HandleTransientHttpError()
                .OrResult(res => res.StatusCode != System.Net.HttpStatusCode.OK)
                .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) + TimeSpan.FromMilliseconds(new Random().Next(0, 100)), (result, timeSpan, current, context) =>
            {
                Console.WriteLine($"------------------------------------");
                Console.WriteLine($"StatusCode={result.Result?.StatusCode}");
                Console.WriteLine($"Exception={result.Exception?.Message}");
                Console.WriteLine($"正在进行第{current}次重试,间隔{timeSpan.TotalMilliseconds}秒");
            })
                );


            // 方法1:
            var policyRegister = new PolicyRegistry();

            policyRegister.Add("MyPolicy", HttpPolicyExtensions.HandleTransientHttpError().Retry(5));
            services.AddPolicyRegistry(policyRegister);
            services.AddGrpcClient <Greeter.GreeterClient>(opt =>
            {
                opt.Address = new Uri("https://localhost:8001");
            })
            .AddPolicyHandlerFromRegistry("MyPolicy");

            // 方法2:
            services.AddGrpcClient <Greeter.GreeterClient>(opt =>
            {
                opt.Address = new Uri("https://localhost:8001");
            })
            .AddPolicyHandler(
                HttpPolicyExtensions.HandleTransientHttpError()
                .OrResult(res => res.StatusCode != System.Net.HttpStatusCode.OK)
                .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) + TimeSpan.FromMilliseconds(new Random().Next(0, 100)), (result, timeSpan, current, context) =>
            {
            })
                );


            // 方法3:
            services.AddGrpcClient <Greeter.GreeterClient>(opt =>
            {
                opt.Address = new Uri("https://localhost:8001");
            })
            .AddPolicyHandler((serviceProvider, responseMessage) =>
            {
                var configuration = serviceProvider.GetService <IConfiguration>();
                var options       = serviceProvider.GetService <IOptions <RetryOptions> >();
                return(HttpPolicyExtensions.HandleTransientHttpError()
                       .OrResult(res => res.StatusCode != System.Net.HttpStatusCode.OK)
                       .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)) + TimeSpan.FromMilliseconds(new Random().Next(0, 100)), (result, timeSpan, current, context) =>
                {
                }));
            });
            var serviceProvider = services.BuildServiceProvider();
            await serviceProvider.GetService <Greeter.GreeterClient>().SayHelloAsync(new HelloRequest()
            {
                Name = "长安书小妆"
            });
        }
示例#20
0
 /// <summary>
 /// 熔断策略
 /// </summary>
 public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError() // System.Net.Http.HttpRequestException情况
            .CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
 }
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            //Test
            //services.Configure<FormOptions>(x => x.MultipartBodyLengthLimit = 4294967295);

            //AppSettings
            services.AddSingleton(Configuration.GetSection("ConfigHelp").Get <ConfigHelp>());

            //---Policy

            //2 P
            var retryPolicy = HttpPolicyExtensions
                              .HandleTransientHttpError()
                              .RetryAsync(3);
            var noOp = Policy.NoOpAsync().AsAsyncPolicy <HttpResponseMessage>();

            //3 P
            var registry    = services.AddPolicyRegistry();
            var timeout     = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(10));
            var longTimeout = Policy.TimeoutAsync <HttpResponseMessage>(TimeSpan.FromSeconds(30));

            registry.Add("regular", timeout);
            registry.Add("long", longTimeout);


            //IOC
            services.AddScoped <IHttpClientFactoryBase, HttpClientFactoryBase>();
            services.AddScoped <ICountryService, CountryManager>();
            //

            // ---- IOC HttpClientFactory----//
            services.AddTransient <TimingHandler>();
            services.AddTransient <AuthTokenHandler>();
            services.AddTransient <LogHandler>();
            services.AddTransient <ValidateHeaderHandler>();

            // ---- Base HttpClientFactory----//
            services.AddHttpClient();



            // ---- Name HttpClientFactory----//
            services.AddHttpClient(namedClients.FarmerExpert.ToString(), c =>
            {
                c.BaseAddress = new Uri(ConfigHelp.WebApiURL);

                /*
                 * c.DefaultRequestHeaders.Add("CustomHeaderKey", "It-is-a-HttpClientFactory-Sample");
                 * c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                 * c.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue
                 * {
                 *  NoCache = true,
                 *  NoStore = true,
                 *  MaxAge = new TimeSpan(0),
                 *  MustRevalidate = true
                 * };
                 */
            });

            /*
             * .AddPolicyHandlerFromRegistry("regular");
             */
            /*
             * .AddPolicyHandler(request => request.Method == HttpMethod.Get ? retryPolicy : noOp);
             */
            /*
             * .AddPolicyHandler(Policy.TimeoutAsync(20).AsAsyncPolicy<HttpResponseMessage>());
             * .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMessage>(TimeSpan.FromSeconds(10))) //Time out policy ekleyerek, gidecek requestlerin en fazla 10 sn bekledikten sonra eðer response alamazsa doðrudan polly tarafýndan hataya düþürülmesini saðladýk
             * .AddTransientHttpErrorPolicy(p => p.RetryAsync(3)); // Haberleþme sýrasýnda geçici sorunlar olduðunda 3 kere yeniden denenmesini istedik. Anlýk internet kayýplarý, server anlýk olarak response verememesi available olamamasý gibi durumlarda request 3 kere yeniden denenecek.(RetryPattern)
             */
            /*
             * .AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[]
             * {
             *  TimeSpan.FromSeconds(1),
             *  TimeSpan.FromSeconds(5),
             *  TimeSpan.FromSeconds(10)
             * }));
             */
            /*
             * .AddHttpMessageHandler<TimingHandler>()
             * .AddHttpMessageHandler<AuthTokenHandler>()
             * .AddHttpMessageHandler<LogHandler>()
             * .AddHttpMessageHandler<ValidateHeaderHandler>();
             */
            /*
             * .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
             * {
             *  AllowAutoRedirect = false,
             *  AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
             * });
             */
            /*
             * .SetHandlerLifetime(TimeSpan.FromMinutes(5));
             */



            // ---- Typed Clients HttpClientFactory----//
            services.AddHttpClient <IFarmerExpertHttpClient, FarmerExpertHttpClient>();

            /*
             * .ConfigurePrimaryHttpMessageHandler(messageHandler =>
             * {
             *  var handler = new HttpClientHandler();
             *  if (handler.SupportsAutomaticDecompression)
             *  {
             *      handler.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
             *  }
             *  return handler;
             * })
             */

            /*
             * .SetHandlerLifetime(TimeSpan.FromMinutes(5));
             */

            /*
             * http://enesaysan.com/software/polly-ve-net-core-3-0-retry-pattern/
             * https://www.stevejgordon.co.uk/httpclientfactory-using-polly-for-transient-fault-handling
             * https://github.com/aspnet/HttpClientFactory/blob/master/samples/HttpClientFactorySample/Program.cs
             * https://erhanballieker.com/2019/03/15/asp-net-core-httpclientfactory-refit/
             * https://erhanballieker.com/2019/03/27/asp-net-core-delegatinghandler/
             * https://www.stevejgordon.co.uk/httpclientfactory-aspnetcore-outgoing-request-middleware-pipeline-delegatinghandlers
             * https://www.stevejgordon.co.uk/httpclientfactory-using-polly-for-transient-fault-handling
             * https://tr.coredump.biz/questions/50747749/how-to-use-httpclienthandler-with-httpclientfactory-in-net-core
             * https://github.com/aspnet/HttpClientFactory/issues/71
             */
        }
 public TransientRetryHandler(Func <PolicyBuilder <HttpResponseMessage>, IAsyncPolicy <HttpResponseMessage> > configurePolicy)
     : base(configurePolicy(HttpPolicyExtensions.HandleTransientHttpError()))
 {
 }
示例#23
0
 public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy(CircuitBreakerPolicyOptions options)
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(options.ExceptionsAllowedBeforeBreaking, options.DurationOfBreak));
 }
示例#24
0
        public override void Configure(IFunctionsHostBuilder builder)
        {
            // We need to get the app directory this way.  Using Environment.CurrentDirectory doesn't work in Azure
            ExecutionContextOptions executioncontextoptions = builder.Services.BuildServiceProvider()
                                                              .GetService <IOptions <ExecutionContextOptions> >().Value;
            string currentDirectory = executioncontextoptions.AppDirectory;

            IConfigurationBuilder configBuilder = new ConfigurationBuilder()
                                                  .SetBasePath(currentDirectory)
                                                  .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                                                  .AddEnvironmentVariables();

            IConfigurationRoot config = configBuilder.Build();

            Dictionary <HttpClientConfigName, ApiConfig> httpClientConfigs = config.GetSection("Apis").Get <Dictionary <HttpClientConfigName, ApiConfig> >();

            var retryPolicy = HttpPolicyExtensions
                              .HandleTransientHttpError()
                              .RetryAsync(3);

            IEnumerable <TimeSpan> timeSpans = new[]
            {
                TimeSpan.FromSeconds(1),
                TimeSpan.FromSeconds(5),
                TimeSpan.FromSeconds(10),
                TimeSpan.FromSeconds(20)
            };

            foreach (KeyValuePair <HttpClientConfigName, ApiConfig> httpClientConfig in httpClientConfigs)
            {
                builder.Services.AddHttpClient(httpClientConfig.Key.ToString(), c =>
                {
                    c.BaseAddress = new Uri(httpClientConfig.Value.BaseAddress);

                    c.Timeout = httpClientConfig.Value.Timeout ?? new TimeSpan(0, 0, 0, 30);

                    foreach (KeyValuePair <string, string> header in httpClientConfig.Value.Headers)
                    {
                        c.DefaultRequestHeaders.Add(header.Key, header.Value);
                    }
                    c.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
                    c.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("deflate"));
                }).ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
                {
                    MaxConnectionsPerServer = httpClientConfig.Value.MaxConnectionsPerServer ?? 15,
                    AutomaticDecompression  = DecompressionMethods.GZip | DecompressionMethods.Deflate
                })
                .AddTransientHttpErrorPolicy(x => x.WaitAndRetryAsync(timeSpans));
            }

            IConfigurationSection applicationConfigSettings = config.GetSection("ApplicationConfig");

            builder.Services.Configure <ApplicationConfig>(applicationConfigSettings);

            builder.Services.AddTransient <IHttpClientWrapper, HttpClientWrapper>();
            builder.Services.AddSingleton <IReportsService, ReportsService>();
            builder.Services.AddSingleton <IConnectCommunicationService, ConnectCommunicationService>();
            builder.Services.AddSingleton <IConnectUserService, ConnectUserService>();
            builder.Services.AddSingleton <IConnectRequestService, ConnectRequestService>();
            builder.Services.AddSingleton <IConnectVerificationService, ConnectVerificationService>();
        }
示例#25
0
文件: Startup.cs 项目: overbit/janus
 private static IAsyncPolicy <HttpResponseMessage> GetBankApiCircuitBreakerPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .CircuitBreakerAsync(5, TimeSpan.FromSeconds(15)));
 }
示例#26
0
 private static AsyncRetryPolicy <System.Net.Http.HttpResponseMessage> GetHttpRetryPolicy()
 {
     return(HttpPolicyExtensions
            .HandleTransientHttpError()
            .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(1)));
 }
示例#27
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure <CookiePolicyOptions>(
                options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded    = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureAD(options => this.configuration.Bind("AzureAd", options));

            services.AddAuthentication(AzureADDefaults.JwtBearerAuthenticationScheme)
            .AddAzureADBearer(options => this.configuration.Bind("AzureAd", options));

            AADAuthHelper.AdminList = this.configuration["ISVPortal:AdminAccounts"].Split(';', StringSplitOptions.RemoveEmptyEntries);

            AADAuthHelper.AdminTenantId = this.configuration["ISVPortal:AdminTenant"];

            services.Configure <JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, options =>
            {
                // This is a Microsoft identity platform web API.
                options.Authority += "/v2.0";

                // The web API accepts as audiences both the Client ID (options.Audience) and api://{ClientID}.
                options.TokenValidationParameters.ValidAudiences = new[]
                {
                    options.Audience,
                    $"api://{options.Audience}",
                    this.configuration["AzureAD:ClientId"],
                    $"api://{this.configuration["AzureAD:ClientId"]}"
                };
                options.ClaimsIssuer = @"https://sts.windows.net/{tenantid}/";

                // Instead of using the default validation (validating against a single tenant,
                // as we do in line-of-business apps),
                // we inject our own multitenant validation logic (which even accepts both v1 and v2 tokens).
                options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate;
            });

            services.Configure <CookieAuthenticationOptions>(
                AzureADDefaults.CookieScheme,
                options => options.AccessDeniedPath = "/Subscriptions/NotAuthorized");

            services.Configure <OpenIdConnectOptions>(
                AzureADDefaults.OpenIdScheme,
                options =>
            {
                //options.Authority = options.Authority + "/v2.0/"; // Azure AD v2.0

                options.TokenValidationParameters.ValidateIssuer =
                    false;         // accept several tenants (here simplified)
            });


            services.Configure <DashboardOptions>(this.configuration.GetSection("Dashboard"));

            services.Configure <AzureOptions>(this.configuration.GetSection("Azure"));

            services.Configure <ApiBehaviorOptions>(x =>
            {
                x.InvalidModelStateResponseFactory = context =>
                {
                    var problemDetails = new ErrorModel(context);
                    return(new BadRequestObjectResult(problemDetails)
                    {
                        ContentTypes = { "application/problem+json", "application/problem+xml" }
                    });
                };
            });

            services.AddOptions <SecuredFulfillmentClientConfiguration>().Configure(
                options => {
                this.configuration.Bind("FulfillmentClient", options);
                this.configuration.Bind("SecuredCredentials:Marketplace", options);
            }
                );
            services.AddHttpClient <IFulfillmentClient, FulfillmentClient>()
            .SetHandlerLifetime(TimeSpan.FromMinutes(5))      //Set lifetime to five minutes
            .AddPolicyHandler(
                (services, request) => HttpPolicyExtensions.HandleTransientHttpError()
                .OrResult(msg => ExceptionUtils.IsHttpErrorCodeRetryable(msg.StatusCode))
                .WaitAndRetryAsync(
                    3,
                    retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
                    onRetry: (result, timeSpan, retryCount, context) =>
            {
                if (result.Exception != null)
                {
                    services.GetService <ILogger <IFulfillmentClient> >()?
                    .LogWarning($"An exception occurred on retry {retryCount} at {context.OperationKey} with message {result.Exception.Message}");
                }
                else
                {
                    services.GetService <ILogger <IFulfillmentClient> >()?
                    .LogError($"An unsuccessful status code {result.Result.StatusCode} was received on retry {retryCount} at {context.OperationKey}");
                }
            }
                    ));

            // Hack to save the host name and port during the handling the request. Please see the WebhookController and ContosoWebhookHandler implementations
            services.AddSingleton <ContosoWebhookHandlerOptions>();


            services.TryAddScoped <IWebhookProcessor, WebhookProcessor>();

            services.TryAddScoped <IFulfillmentManager, FulfillmentManager>();

            // Register the provisioning client
            services.AddOptions <SecuredProvisioningClientConfiguration>().Configure(
                options => {
                this.configuration.Bind("ProvisioningClient", options);
                this.configuration.Bind("SecuredCredentials:ResourceManager", options);
            }
                );
            //services.TryAddScoped<IProvisioningClient, ProvisioningClient>();
            services.AddHttpClient <IProvisioningClient, ProvisioningClient>()
            .SetHandlerLifetime(TimeSpan.FromMinutes(5));

            // Get the connection string from appsettings.json
            string connectionString = this.configuration.GetValue <string>(this.configuration["SecuredCredentials:Database:ConnectionString"]);

            // Database context must be registered with the dependency injection (DI) container
            services.AddDbContext <SqlDbContext>(options =>
                                                 options.UseSqlServer(connectionString));

            // Register the db context interface
            services.TryAddScoped <ISqlDbContext, SqlDbContext>();


            services.AddOptions <StorageAccountConfigurationOption>().Configure(
                options => {
                this.configuration.Bind("SecuredCredentials:StorageAccount", options);
            }
                );

            // Register the storage utility interface
            services.TryAddScoped <IStorageUtility, StorageUtility>();
            services.TryAddScoped <IKeyVaultHelper, KeyVaultHelper>();
            // Register the provisioning helper
            services.TryAddScoped <IMarketplaceNotificationHandler, ProvisioningHelper>();

            // Register the entity services
            services.TryAddScoped <IOfferService, OfferService>();
            services.TryAddScoped <IArmTemplateService, ArmTemplateService>();
            services.TryAddScoped <IPlanService, PlanService>();
            services.TryAddScoped <ISubscriptionService, SubscriptionService>();
            services.TryAddScoped <IAadSecretTmpService, AadSecretTmpService>();
            services.TryAddScoped <IArmTemplateParameterService, ArmTemplateParameterService>();
            services.TryAddScoped <ICustomMeterService, CustomMeterService>();
            services.TryAddScoped <ICustomMeterDimensionService, CustomMeterDimensionService>();
            services.TryAddScoped <IIpConfigService, IpConfigService>();
            services.TryAddScoped <IOfferParameterService, OfferParameterService>();
            services.TryAddScoped <IRestrictedUserService, RestrictedUserService>();
            services.TryAddScoped <IWebhookService, WebhookService>();
            services.TryAddScoped <IWebhookParameterService, WebhookParameterService>();
            services.TryAddScoped <IProvisioningService, ProvisioningService>();
            services.TryAddScoped <IIpAddressService, IpAddressService>();
            services.TryAddScoped <ISubscriptionParameterService, SubscriptionParameterService>();
            services.TryAddScoped <IWebhookWebhookParameterService, WebhookWebhookParameterService>();
            services.TryAddScoped <IArmTemplateArmTemplateParameterService, ArmTemplateArmTemplateParameterService>();

            // Register luna db client
            services.AddHttpClient("Luna", x => { x.BaseAddress = new Uri(configuration.GetValue <string>("LunaClient:BaseUri")); });
            services.TryAddScoped <LunaClient>();

            services.AddCors();

            services.AddRazorPages();

            services.AddApiVersioning(o => {
                DateTime groupVersion = DateTime.ParseExact(apiVersion, "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
                ApiVersion latest     = new ApiVersion(groupVersion);

                o.ReportApiVersions = true;
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = latest;

                o.Conventions.Controller <OfferController>().HasApiVersion(latest);
                o.Conventions.Controller <ArmTemplateController>().HasApiVersion(latest);
                o.Conventions.Controller <PlanController>().HasApiVersion(latest);
                o.Conventions.Controller <SubscriptionController>().HasApiVersion(latest);
                o.Conventions.Controller <ArmTemplateParameterController>().HasApiVersion(latest);
                o.Conventions.Controller <CustomMeterController>().HasApiVersion(latest);
                o.Conventions.Controller <CustomMeterDimensionController>().HasApiVersion(latest);
                o.Conventions.Controller <IpConfigController>().HasApiVersion(latest);
                o.Conventions.Controller <OfferParameterController>().HasApiVersion(latest);
                o.Conventions.Controller <RestrictedUserController>().HasApiVersion(latest);
                o.Conventions.Controller <WebhookController>().HasApiVersion(latest);
                o.Conventions.Controller <WebhookParameterController>().HasApiVersion(latest);
            });

            // Register the Swagger generator, defining 1 or more Swagger documents
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc(apiVersion, new OpenApiInfo {
                    Title = "Luna Dashboard API", Version = apiVersion
                });

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            });
            services.AddApplicationInsightsTelemetry();
        }
示例#28
0
        public async Task <DeveloperApiKeyResult> GetApiKeyOrNullAsync(bool invalidateCache = false)
        {
            if (invalidateCache)
            {
                _apiKeyResult = null;
            }

            if (_apiKeyResult != null)
            {
                return(_apiKeyResult);
            }

            var url = $"{CliUrls.WwwAbpIo}api/license/api-key";

            using (var client = new CliHttpClient())
            {
                var response = await HttpPolicyExtensions
                               .HandleTransientHttpError()
                               .OrResult(msg => !msg.IsSuccessStatusCode)
                               .WaitAndRetryAsync(new[]
                {
                    TimeSpan.FromSeconds(1),
                    TimeSpan.FromSeconds(3),
                    TimeSpan.FromSeconds(7)
                },
                                                  (responseMessage, timeSpan, retryCount, context) =>
                {
                    if (responseMessage.Exception != null)
                    {
                        _logger.LogWarning(
                            $"{retryCount}. request attempt failed to {url} with an error: \"{responseMessage.Exception.Message}\". " +
                            $"Waiting {timeSpan.TotalSeconds} secs for the next try...");
                    }
                    else if (responseMessage.Result != null)
                    {
                        _logger.LogWarning(
                            $"{retryCount}. request attempt failed {url} with {(int)responseMessage.Result.StatusCode}-{responseMessage.Result.ReasonPhrase}. " +
                            $"Waiting {timeSpan.TotalSeconds} secs for the next try...");
                    }
                })
                               .ExecuteAsync(async() => await client.GetAsync(url).ConfigureAwait(false)).ConfigureAwait(false);

                if (!response.IsSuccessStatusCode)
                {
                    throw new Exception($"ERROR: Remote server returns '{response.StatusCode}'");
                }

                await RemoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(response).ConfigureAwait(false);

                var responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                var apiKeyResult = JsonSerializer.Deserialize <DeveloperApiKeyResult>(responseContent);

                if (apiKeyResult == null ||
                    string.IsNullOrEmpty(apiKeyResult.ApiKey))
                {
                    _logger.LogError("Couldn't retrieve your NuGet API key!");
                    _logger.LogWarning(File.Exists(CliPaths.AccessToken)
                        ? "Make sure you have an active session and license on commercial.abp.io. To re-sign in you can use the CLI command \"abp login <username>\"."
                        : "You are not signed in to commercial.abp.io. Use the CLI command \"abp login <username>\" to sign in.");

                    return(null);
                }

                return(apiKeyResult);
            }
        }
示例#29
0
 private IAsyncPolicy <HttpResponseMessage> GetRetryPolicy()
 {
     return(HttpPolicyExtensions.HandleTransientHttpError()
            .OrResult(msg => msg.StatusCode == HttpStatusCode.NotFound)
            .WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))));
 }
 private static IAsyncPolicy <HttpResponseMessage> GetRetryPolicy() =>
 HttpPolicyExtensions
 .HandleTransientHttpError()
 .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
 .WaitAndRetryAsync(5, retryAttempt =>
                    TimeSpan.FromMinutes(1));