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"),
private static IAsyncPolicy <HttpResponseMessage> GetBankApiRetryPolicy() { return(HttpPolicyExtensions .HandleTransientHttpError() .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)))); }
private IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy() { return(HttpPolicyExtensions.HandleTransientHttpError().CircuitBreakerAsync(3, TimeSpan.FromSeconds(30))); }
// 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)); }
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)))); }
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)))); }
public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy() => HttpPolicyExtensions .HandleTransientHttpError() .CircuitBreakerAsync(2, TimeSpan.FromSeconds(30));
/// <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); }
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(); }
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)))); }
/// <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));
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))); }); }
private IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPattern() { return(HttpPolicyExtensions .HandleTransientHttpError() .CircuitBreakerAsync(handledEventsAllowedBeforeBreaking: 3, TimeSpan.FromSeconds(30))); }
private static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy() { return(HttpPolicyExtensions .HandleTransientHttpError() .CircuitBreakerAsync(2, TimeSpan.FromSeconds(30))); //After two times falls it will not retry until 30 sec. }
private static Polly.Retry.AsyncRetryPolicy <HttpResponseMessage> RetryPolicy(int retries) => HttpPolicyExtensions .HandleTransientHttpError() .Or <TimeoutRejectedException>() .RetryAsync(retries);
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); } }
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 = "长安书小妆" }); }
/// <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())) { }
public static IAsyncPolicy <HttpResponseMessage> GetCircuitBreakerPolicy(CircuitBreakerPolicyOptions options) { return(HttpPolicyExtensions .HandleTransientHttpError() .CircuitBreakerAsync(options.ExceptionsAllowedBeforeBreaking, options.DurationOfBreak)); }
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>(); }
private static IAsyncPolicy <HttpResponseMessage> GetBankApiCircuitBreakerPolicy() { return(HttpPolicyExtensions .HandleTransientHttpError() .CircuitBreakerAsync(5, TimeSpan.FromSeconds(15))); }
private static AsyncRetryPolicy <System.Net.Http.HttpResponseMessage> GetHttpRetryPolicy() { return(HttpPolicyExtensions .HandleTransientHttpError() .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(1))); }
// 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(); }
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); } }
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));