Fix formatting
This commit is contained in:
		
							parent
							
								
									9d38de0c83
								
							
						
					
					
						commit
						451d79f7b9
					
				| @ -1,4 +1,4 @@ | ||||
| await BuildWebHost(args).RunAsync(); | ||||
| await BuildWebHost(args).RunAsync(); | ||||
| IWebHost BuildWebHost(string[] args) => | ||||
|     WebHost | ||||
|         .CreateDefaultBuilder(args) | ||||
|  | ||||
| @ -3,12 +3,14 @@ using Microsoft.Azure.Amqp.Framing; | ||||
| using Microsoft.Extensions.Configuration; | ||||
| 
 | ||||
| var appName = "Basket.API"; | ||||
| var builder = WebApplication.CreateBuilder(new WebApplicationOptions { | ||||
| var builder = WebApplication.CreateBuilder(new WebApplicationOptions | ||||
| { | ||||
|     Args = args, | ||||
|     ApplicationName = typeof(Program).Assembly.FullName, | ||||
|     ContentRootPath = Directory.GetCurrentDirectory() | ||||
| }); | ||||
| if (builder.Configuration.GetValue<bool>("UseVault", false)) { | ||||
| if (builder.Configuration.GetValue<bool>("UseVault", false)) | ||||
| { | ||||
|     TokenCredential credential = new ClientSecretCredential( | ||||
|            builder.Configuration["Vault:TenantId"], | ||||
|         builder.Configuration["Vault:ClientId"], | ||||
| @ -16,29 +18,36 @@ if (builder.Configuration.GetValue<bool>("UseVault", false)) { | ||||
|     builder.Configuration.AddAzureKeyVault(new Uri($"https://{builder.Configuration["Vault:Name"]}.vault.azure.net/"), credential); | ||||
| } | ||||
| 
 | ||||
| builder.Services.AddGrpc(options => { | ||||
| builder.Services.AddGrpc(options => | ||||
| { | ||||
|     options.EnableDetailedErrors = true; | ||||
| }); | ||||
| builder.Services.AddApplicationInsightsTelemetry(builder.Configuration); | ||||
| builder.Services.AddApplicationInsightsKubernetesEnricher(); | ||||
| builder.Services.AddControllers(options => { | ||||
| builder.Services.AddControllers(options => | ||||
| { | ||||
|     options.Filters.Add(typeof(HttpGlobalExceptionFilter)); | ||||
|     options.Filters.Add(typeof(ValidateModelStateFilter)); | ||||
| 
 | ||||
| }) // Added for functional tests | ||||
|             .AddApplicationPart(typeof(BasketController).Assembly) | ||||
|             .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); | ||||
| builder.Services.AddSwaggerGen(options => { | ||||
|     options.SwaggerDoc("v1", new OpenApiInfo { | ||||
| builder.Services.AddSwaggerGen(options => | ||||
| { | ||||
|     options.SwaggerDoc("v1", new OpenApiInfo | ||||
|     { | ||||
|         Title = "eShopOnContainers - Basket HTTP API", | ||||
|         Version = "v1", | ||||
|         Description = "The Basket Service HTTP API" | ||||
|     }); | ||||
| 
 | ||||
|     options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { | ||||
|     options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme | ||||
|     { | ||||
|         Type = SecuritySchemeType.OAuth2, | ||||
|         Flows = new OpenApiOAuthFlows() { | ||||
|             Implicit = new OpenApiOAuthFlow() { | ||||
|         Flows = new OpenApiOAuthFlows() | ||||
|         { | ||||
|             Implicit = new OpenApiOAuthFlow() | ||||
|             { | ||||
|                 AuthorizationUrl = new Uri($"{builder.Configuration.GetValue<string>("IdentityUrlExternal")}/connect/authorize"), | ||||
|                 TokenUrl = new Uri($"{builder.Configuration.GetValue<string>("IdentityUrlExternal")}/connect/token"), | ||||
|                 Scopes = new Dictionary<string, string>() { { "basket", "Basket API" } } | ||||
| @ -54,14 +63,17 @@ JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); | ||||
| 
 | ||||
| var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl"); | ||||
| 
 | ||||
| builder.Services.AddAuthentication("Bearer").AddJwtBearer(options => { | ||||
| builder.Services.AddAuthentication("Bearer").AddJwtBearer(options => | ||||
| { | ||||
|     options.Authority = identityUrl; | ||||
|     options.RequireHttpsMetadata = false; | ||||
|     options.Audience = "basket"; | ||||
|     options.TokenValidationParameters.ValidateAudience = false; | ||||
| }); | ||||
| builder.Services.AddAuthorization(options => { | ||||
|     options.AddPolicy("ApiScope", policy => { | ||||
| builder.Services.AddAuthorization(options => | ||||
| { | ||||
|     options.AddPolicy("ApiScope", policy => | ||||
|     { | ||||
|         policy.RequireAuthenticatedUser(); | ||||
|         policy.RequireClaim("scope", "basket"); | ||||
|     }); | ||||
| @ -71,7 +83,8 @@ builder.Services.AddCustomHealthCheck(builder.Configuration); | ||||
| 
 | ||||
| builder.Services.Configure<BasketSettings>(builder.Configuration); | ||||
| 
 | ||||
| builder.Services.AddSingleton<ConnectionMultiplexer>(sp => { | ||||
| builder.Services.AddSingleton<ConnectionMultiplexer>(sp => | ||||
| { | ||||
|     var settings = sp.GetRequiredService<IOptions<BasketSettings>>().Value; | ||||
|     var configuration = ConfigurationOptions.Parse(settings.ConnectionString, true); | ||||
| 
 | ||||
| @ -79,32 +92,40 @@ builder.Services.AddSingleton<ConnectionMultiplexer>(sp => { | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| if (builder.Configuration.GetValue<bool>("AzureServiceBusEnabled")) { | ||||
|     builder.Services.AddSingleton<IServiceBusPersisterConnection>(sp => { | ||||
| if (builder.Configuration.GetValue<bool>("AzureServiceBusEnabled")) | ||||
| { | ||||
|     builder.Services.AddSingleton<IServiceBusPersisterConnection>(sp => | ||||
|     { | ||||
|         var serviceBusConnectionString = builder.Configuration["EventBusConnection"]; | ||||
| 
 | ||||
|         return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); | ||||
|     }); | ||||
| } | ||||
| else { | ||||
|     builder.Services.AddSingleton<IRabbitMQPersistentConnection>(sp => { | ||||
| else | ||||
| { | ||||
|     builder.Services.AddSingleton<IRabbitMQPersistentConnection>(sp => | ||||
|     { | ||||
|         var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); | ||||
| 
 | ||||
|         var factory = new ConnectionFactory() { | ||||
|         var factory = new ConnectionFactory() | ||||
|         { | ||||
|             HostName = builder.Configuration["EventBusConnection"], | ||||
|             DispatchConsumersAsync = true | ||||
|         }; | ||||
| 
 | ||||
|         if (!string.IsNullOrEmpty(builder.Configuration["EventBusUserName"])) { | ||||
|         if (!string.IsNullOrEmpty(builder.Configuration["EventBusUserName"])) | ||||
|         { | ||||
|             factory.UserName = builder.Configuration["EventBusUserName"]; | ||||
|         } | ||||
| 
 | ||||
|         if (!string.IsNullOrEmpty(builder.Configuration["EventBusPassword"])) { | ||||
|         if (!string.IsNullOrEmpty(builder.Configuration["EventBusPassword"])) | ||||
|         { | ||||
|             factory.Password = builder.Configuration["EventBusPassword"]; | ||||
|         } | ||||
| 
 | ||||
|         var retryCount = 5; | ||||
|         if (!string.IsNullOrEmpty(builder.Configuration["EventBusRetryCount"])) { | ||||
|         if (!string.IsNullOrEmpty(builder.Configuration["EventBusRetryCount"])) | ||||
|         { | ||||
|             retryCount = int.Parse(builder.Configuration["EventBusRetryCount"]); | ||||
|         } | ||||
| 
 | ||||
| @ -112,7 +133,8 @@ else { | ||||
|     }); | ||||
| } | ||||
| builder.Services.RegisterEventBus(builder.Configuration); | ||||
| builder.Services.AddCors(options => { | ||||
| builder.Services.AddCors(options => | ||||
| { | ||||
|     options.AddPolicy("CorsPolicy", | ||||
|         builder => builder | ||||
|         .SetIsOriginAllowed((host) => true) | ||||
| @ -128,39 +150,47 @@ builder.Services.AddOptions(); | ||||
| builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()); | ||||
| builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | ||||
| builder.Configuration.AddEnvironmentVariables(); | ||||
| builder.WebHost.UseKestrel(options => { | ||||
| builder.WebHost.UseKestrel(options => | ||||
| { | ||||
|     var ports = GetDefinedPorts(builder.Configuration); | ||||
|     options.Listen(IPAddress.Any, ports.httpPort, listenOptions => { | ||||
|     options.Listen(IPAddress.Any, ports.httpPort, listenOptions => | ||||
|     { | ||||
|         listenOptions.Protocols = HttpProtocols.Http1AndHttp2; | ||||
|     }); | ||||
| 
 | ||||
|     options.Listen(IPAddress.Any, ports.grpcPort, listenOptions => { | ||||
|     options.Listen(IPAddress.Any, ports.grpcPort, listenOptions => | ||||
|     { | ||||
|         listenOptions.Protocols = HttpProtocols.Http2; | ||||
|     }); | ||||
| 
 | ||||
| }); | ||||
| builder.WebHost.CaptureStartupErrors(false); | ||||
| builder.Host.UseSerilog(CreateSerilogLogger(builder.Configuration)); | ||||
| builder.WebHost.UseFailing(options => { | ||||
| builder.WebHost.UseFailing(options => | ||||
| { | ||||
|     options.ConfigPath = "/Failing"; | ||||
|     options.NotFilteredPaths.AddRange(new[] { "/hc", "/liveness" }); | ||||
| }); | ||||
| var app = builder.Build(); | ||||
| 
 | ||||
| if (app.Environment.IsDevelopment()) { | ||||
| if (app.Environment.IsDevelopment()) | ||||
| { | ||||
|     app.UseDeveloperExceptionPage(); | ||||
| } | ||||
| else { | ||||
| else | ||||
| { | ||||
|     app.UseExceptionHandler("/Home/Error"); | ||||
| } | ||||
| 
 | ||||
| var pathBase = app.Configuration["PATH_BASE"]; | ||||
| if (!string.IsNullOrEmpty(pathBase)) { | ||||
| if (!string.IsNullOrEmpty(pathBase)) | ||||
| { | ||||
|     app.UsePathBase(pathBase); | ||||
| } | ||||
| 
 | ||||
| app.UseSwagger() | ||||
|             .UseSwaggerUI(setup => { | ||||
|             .UseSwaggerUI(setup => | ||||
|             { | ||||
|                 setup.SwaggerEndpoint($"{(!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty)}/swagger/v1/swagger.json", "Basket.API V1"); | ||||
|                 setup.OAuthClientId("basketswaggerui"); | ||||
|                 setup.OAuthAppName("Basket Swagger UI"); | ||||
| @ -176,26 +206,32 @@ app.UseStaticFiles(); | ||||
| app.MapGrpcService<BasketService>(); | ||||
| app.MapDefaultControllerRoute(); | ||||
| app.MapControllers(); | ||||
| app.MapGet("/_proto/", async ctx => { | ||||
| app.MapGet("/_proto/", async ctx => | ||||
| { | ||||
|     ctx.Response.ContentType = "text/plain"; | ||||
|     using var fs = new FileStream(Path.Combine(app.Environment.ContentRootPath, "Proto", "basket.proto"), FileMode.Open, FileAccess.Read); | ||||
|     using var sr = new StreamReader(fs); | ||||
|     while (!sr.EndOfStream) { | ||||
|     while (!sr.EndOfStream) | ||||
|     { | ||||
|         var line = await sr.ReadLineAsync(); | ||||
|         if (line != "/* >>" || line != "<< */") { | ||||
|         if (line != "/* >>" || line != "<< */") | ||||
|         { | ||||
|             await ctx.Response.WriteAsync(line); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| app.MapHealthChecks("/hc", new HealthCheckOptions() { | ||||
| app.MapHealthChecks("/hc", new HealthCheckOptions() | ||||
| { | ||||
|     Predicate = _ => true, | ||||
|     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse | ||||
| }); | ||||
| app.MapHealthChecks("/liveness", new HealthCheckOptions { | ||||
| app.MapHealthChecks("/liveness", new HealthCheckOptions | ||||
| { | ||||
|     Predicate = r => r.Name.Contains("self") | ||||
| }); | ||||
| ConfigureEventBus(app); | ||||
| try { | ||||
| try | ||||
| { | ||||
|     Log.Information("Configuring web host ({ApplicationContext})...", Program.AppName); | ||||
| 
 | ||||
| 
 | ||||
| @ -204,15 +240,18 @@ try { | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| catch (Exception ex) { | ||||
| catch (Exception ex) | ||||
| { | ||||
|     Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", Program.AppName); | ||||
|     return 1; | ||||
| } | ||||
| finally { | ||||
| finally | ||||
| { | ||||
|     Log.CloseAndFlush(); | ||||
| } | ||||
| 
 | ||||
| Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { | ||||
| Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) | ||||
| { | ||||
|     var seqServerUrl = configuration["Serilog:SeqServerUrl"]; | ||||
|     var logstashUrl = configuration["Serilog:LogstashgUrl"]; | ||||
|     return new LoggerConfiguration() | ||||
| @ -226,30 +265,37 @@ Serilog.ILogger CreateSerilogLogger(IConfiguration configuration) { | ||||
|         .CreateLogger(); | ||||
| } | ||||
| 
 | ||||
| (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config) { | ||||
| (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config) | ||||
| { | ||||
|     var grpcPort = config.GetValue("GRPC_PORT", 5001); | ||||
|     var port = config.GetValue("PORT", 80); | ||||
|     return (port, grpcPort); | ||||
| } | ||||
| void ConfigureEventBus(IApplicationBuilder app) { | ||||
| void ConfigureEventBus(IApplicationBuilder app) | ||||
| { | ||||
|     var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>(); | ||||
| 
 | ||||
|     eventBus.Subscribe<ProductPriceChangedIntegrationEvent, ProductPriceChangedIntegrationEventHandler>(); | ||||
|     eventBus.Subscribe<OrderStartedIntegrationEvent, OrderStartedIntegrationEventHandler>(); | ||||
| } | ||||
| public partial class Program { | ||||
| public partial class Program | ||||
| { | ||||
| 
 | ||||
|     public static string Namespace = typeof(Program).Assembly.GetName().Name; | ||||
|     public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| public static class CustomExtensionMethods { | ||||
| public static class CustomExtensionMethods | ||||
| { | ||||
| 
 | ||||
| 
 | ||||
|     public static IServiceCollection RegisterEventBus(this IServiceCollection services, IConfiguration configuration) { | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) { | ||||
|             services.AddSingleton<IEventBus, EventBusServiceBus>(sp => { | ||||
|     public static IServiceCollection RegisterEventBus(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) | ||||
|         { | ||||
|             services.AddSingleton<IEventBus, EventBusServiceBus>(sp => | ||||
|             { | ||||
|                 var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>(); | ||||
|                 var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>(); | ||||
|                 var eventBusSubscriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | ||||
| @ -259,15 +305,18 @@ public static class CustomExtensionMethods { | ||||
|                     eventBusSubscriptionsManager, sp, subscriptionName); | ||||
|             }); | ||||
|         } | ||||
|         else { | ||||
|             services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => { | ||||
|         else | ||||
|         { | ||||
|             services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => | ||||
|             { | ||||
|                 var subscriptionClientName = configuration["SubscriptionClientName"]; | ||||
|                 var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>(); | ||||
|                 var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>(); | ||||
|                 var eventBusSubscriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | ||||
| 
 | ||||
|                 var retryCount = 5; | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) { | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) | ||||
|                 { | ||||
|                     retryCount = int.Parse(configuration["EventBusRetryCount"]); | ||||
|                 } | ||||
| 
 | ||||
|  | ||||
| @ -1,11 +1,12 @@ | ||||
| var appName = "Catalog.API"; | ||||
| var builder = WebApplication.CreateBuilder(new WebApplicationOptions { | ||||
| var builder = WebApplication.CreateBuilder(new WebApplicationOptions | ||||
| { | ||||
|     Args = args, | ||||
|     ApplicationName = typeof(Program).Assembly.FullName, | ||||
|     ContentRootPath = Directory.GetCurrentDirectory(), | ||||
|     WebRootPath = "Pics", | ||||
| }); | ||||
| if (builder.Configuration.GetValue<bool>("UseVault", false)) { | ||||
| if (builder.Configuration.GetValue<bool>("UseVault", false)) | ||||
| { | ||||
|     TokenCredential credential = new ClientSecretCredential( | ||||
|         builder.Configuration["Vault:TenantId"], | ||||
|         builder.Configuration["Vault:ClientId"], | ||||
| @ -13,12 +14,15 @@ if (builder.Configuration.GetValue<bool>("UseVault", false)) { | ||||
|     //builder.AddAzureKeyVault(new Uri($"https://{builder.Configuration["Vault:Name"]}.vault.azure.net/"), credential);         | ||||
| } | ||||
| builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); | ||||
| builder.WebHost.UseKestrel(options => { | ||||
| builder.WebHost.UseKestrel(options => | ||||
| { | ||||
|     var ports = GetDefinedPorts(builder.Configuration); | ||||
|     options.Listen(IPAddress.Any, ports.httpPort, listenOptions => { | ||||
|     options.Listen(IPAddress.Any, ports.httpPort, listenOptions => | ||||
|     { | ||||
|         listenOptions.Protocols = HttpProtocols.Http1AndHttp2; | ||||
|     }); | ||||
|     options.Listen(IPAddress.Any, ports.grpcPort, listenOptions => { | ||||
|     options.Listen(IPAddress.Any, ports.grpcPort, listenOptions => | ||||
|     { | ||||
|         listenOptions.Protocols = HttpProtocols.Http2; | ||||
|     }); | ||||
| 
 | ||||
| @ -35,20 +39,24 @@ builder.Services.AddGrpc().Services | ||||
| 
 | ||||
| var app = builder.Build(); | ||||
| 
 | ||||
| if (app.Environment.IsDevelopment()) { | ||||
| if (app.Environment.IsDevelopment()) | ||||
| { | ||||
|     app.UseDeveloperExceptionPage(); | ||||
| } | ||||
| else { | ||||
| else | ||||
| { | ||||
|     app.UseExceptionHandler("/Home/Error"); | ||||
| } | ||||
| 
 | ||||
| var pathBase = app.Configuration["PATH_BASE"]; | ||||
| if (!string.IsNullOrEmpty(pathBase)) { | ||||
| if (!string.IsNullOrEmpty(pathBase)) | ||||
| { | ||||
|     app.UsePathBase(pathBase); | ||||
| } | ||||
| 
 | ||||
| app.UseSwagger() | ||||
|             .UseSwaggerUI(c => { | ||||
|             .UseSwaggerUI(c => | ||||
|             { | ||||
|                 c.SwaggerEndpoint($"{(!string.IsNullOrEmpty(pathBase) ? pathBase : string.Empty)}/swagger/v1/swagger.json", "Catalog.API V1"); | ||||
|             }); | ||||
| 
 | ||||
| @ -56,39 +64,45 @@ app.UseRouting(); | ||||
| app.UseCors("CorsPolicy"); | ||||
| app.MapDefaultControllerRoute(); | ||||
| app.MapControllers(); | ||||
| app.UseFileServer(new FileServerOptions { | ||||
| app.UseFileServer(new FileServerOptions | ||||
| { | ||||
|     FileProvider = new PhysicalFileProvider(Path.Combine(app.Environment.ContentRootPath, "Pics")), | ||||
|     RequestPath = "/pics" | ||||
| }); | ||||
| app.UseStaticFiles(new StaticFileOptions { | ||||
| app.UseStaticFiles(new StaticFileOptions | ||||
| { | ||||
|     FileProvider = new PhysicalFileProvider(Path.Combine(app.Environment.ContentRootPath, "Pics")), | ||||
|     RequestPath = "/pics" | ||||
| }); | ||||
| app.MapGet("/_proto/", async ctx => { | ||||
| app.MapGet("/_proto/", async ctx => | ||||
| { | ||||
|     ctx.Response.ContentType = "text/plain"; | ||||
|     using var fs = new FileStream(Path.Combine(app.Environment.ContentRootPath, "Proto", "catalog.proto"), FileMode.Open, FileAccess.Read); | ||||
|     using var sr = new StreamReader(fs); | ||||
|     while (!sr.EndOfStream) { | ||||
|     while (!sr.EndOfStream) | ||||
|     { | ||||
|         var line = await sr.ReadLineAsync(); | ||||
|         if (line != "/* >>" || line != "<< */") { | ||||
|         if (line != "/* >>" || line != "<< */") | ||||
|         { | ||||
|             await ctx.Response.WriteAsync(line); | ||||
|         } | ||||
|     } | ||||
| }); | ||||
| app.MapGrpcService<CatalogService>(); | ||||
| app.MapHealthChecks("/hc", new HealthCheckOptions() { | ||||
| app.MapHealthChecks("/hc", new HealthCheckOptions() | ||||
| { | ||||
|     Predicate = _ => true, | ||||
|     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse | ||||
| }); | ||||
| app.MapHealthChecks("/liveness", new HealthCheckOptions { | ||||
| app.MapHealthChecks("/liveness", new HealthCheckOptions | ||||
| { | ||||
|     Predicate = r => r.Name.Contains("self") | ||||
| }); | ||||
| 
 | ||||
| ConfigureEventBus(app); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| try { | ||||
| try | ||||
| { | ||||
|     Log.Information("Configuring web host ({ApplicationContext})...", Program.AppName); | ||||
|     using var scope = app.Services.CreateScope(); | ||||
|     var context = scope.ServiceProvider.GetRequiredService<CatalogContext>(); | ||||
| @ -100,50 +114,60 @@ try { | ||||
|     await new CatalogContextSeed().SeedAsync(context, env, settings, logger); | ||||
|     var integEventContext = scope.ServiceProvider.GetRequiredService<IntegrationEventLogContext>(); | ||||
|     await integEventContext.Database.MigrateAsync(); | ||||
|     app.Logger.LogInformation("Starting web host ({ApplicationName})...", appName); | ||||
|     app.Logger.LogInformation("Starting web host ({ApplicationName})...", AppName); | ||||
|     await app.RunAsync(); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| catch (Exception ex) { | ||||
| catch (Exception ex) | ||||
| { | ||||
|     Log.Fatal(ex, "Program terminated unexpectedly ({ApplicationContext})!", Program.AppName); | ||||
|     return 1; | ||||
| } | ||||
| finally { | ||||
| finally | ||||
| { | ||||
|     Log.CloseAndFlush(); | ||||
| } | ||||
| void ConfigureEventBus(IApplicationBuilder app) { | ||||
| void ConfigureEventBus(IApplicationBuilder app) | ||||
| { | ||||
|     var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>(); | ||||
|     eventBus.Subscribe<OrderStatusChangedToAwaitingValidationIntegrationEvent, OrderStatusChangedToAwaitingValidationIntegrationEventHandler>(); | ||||
|     eventBus.Subscribe<OrderStatusChangedToPaidIntegrationEvent, OrderStatusChangedToPaidIntegrationEventHandler>(); | ||||
| } | ||||
| 
 | ||||
| (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config) { | ||||
| (int httpPort, int grpcPort) GetDefinedPorts(IConfiguration config) | ||||
| { | ||||
|     var grpcPort = config.GetValue("GRPC_PORT", 81); | ||||
|     var port = config.GetValue("PORT", 80); | ||||
|     return (port, grpcPort); | ||||
| } | ||||
| 
 | ||||
| public partial class Program { | ||||
| public partial class Program | ||||
| { | ||||
|     public static string Namespace = typeof(Program).Assembly.GetName().Name; | ||||
|     public static string AppName = Namespace.Substring(Namespace.LastIndexOf('.', Namespace.LastIndexOf('.') - 1) + 1); | ||||
| } | ||||
| 
 | ||||
| public static class CustomExtensionMethods { | ||||
|     public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) { | ||||
| public static class CustomExtensionMethods | ||||
| { | ||||
|     public static IServiceCollection AddAppInsight(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         services.AddApplicationInsightsTelemetry(configuration); | ||||
|         services.AddApplicationInsightsKubernetesEnricher(); | ||||
| 
 | ||||
|         return services; | ||||
|     } | ||||
| 
 | ||||
|     public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration) { | ||||
|         services.AddControllers(options => { | ||||
|     public static IServiceCollection AddCustomMVC(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         services.AddControllers(options => | ||||
|         { | ||||
|             options.Filters.Add(typeof(HttpGlobalExceptionFilter)); | ||||
|         }) | ||||
|         .AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true); | ||||
| 
 | ||||
|         services.AddCors(options => { | ||||
|         services.AddCors(options => | ||||
|         { | ||||
|             options.AddPolicy("CorsPolicy", | ||||
|                 builder => builder | ||||
|                 .SetIsOriginAllowed((host) => true) | ||||
| @ -155,7 +179,8 @@ public static class CustomExtensionMethods { | ||||
|         return services; | ||||
|     } | ||||
| 
 | ||||
|     public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) { | ||||
|     public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         var accountName = configuration.GetValue<string>("AzureStorageAccountName"); | ||||
|         var accountKey = configuration.GetValue<string>("AzureStorageAccountKey"); | ||||
| 
 | ||||
| @ -168,7 +193,8 @@ public static class CustomExtensionMethods { | ||||
|                 name: "CatalogDB-check", | ||||
|                 tags: new string[] { "catalogdb" }); | ||||
| 
 | ||||
|         if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey)) { | ||||
|         if (!string.IsNullOrEmpty(accountName) && !string.IsNullOrEmpty(accountKey)) | ||||
|         { | ||||
|             hcBuilder | ||||
|                 .AddAzureBlobStorage( | ||||
|                     $"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net", | ||||
| @ -176,7 +202,8 @@ public static class CustomExtensionMethods { | ||||
|                     tags: new string[] { "catalogstorage" }); | ||||
|         } | ||||
| 
 | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) { | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) | ||||
|         { | ||||
|             hcBuilder | ||||
|                 .AddAzureServiceBusTopic( | ||||
|                     configuration["EventBusConnection"], | ||||
| @ -184,7 +211,8 @@ public static class CustomExtensionMethods { | ||||
|                     name: "catalog-servicebus-check", | ||||
|                     tags: new string[] { "servicebus" }); | ||||
|         } | ||||
|         else { | ||||
|         else | ||||
|         { | ||||
|             hcBuilder | ||||
|                 .AddRabbitMQ( | ||||
|                     $"amqp://{configuration["EventBusConnection"]}", | ||||
| @ -195,20 +223,25 @@ public static class CustomExtensionMethods { | ||||
|         return services; | ||||
|     } | ||||
| 
 | ||||
|     public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) { | ||||
|     public static IServiceCollection AddCustomDbContext(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         services.AddEntityFrameworkSqlServer() | ||||
|             .AddDbContext<CatalogContext>(options => { | ||||
|             .AddDbContext<CatalogContext>(options => | ||||
|             { | ||||
|                 options.UseSqlServer(configuration["ConnectionString"], | ||||
|                                         sqlServerOptionsAction: sqlOptions => { | ||||
|                                         sqlServerOptionsAction: sqlOptions => | ||||
|                                         { | ||||
|                                             sqlOptions.MigrationsAssembly(typeof(Program).GetTypeInfo().Assembly.GetName().Name); | ||||
|                                             //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency  | ||||
|                                             sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); | ||||
|                                         }); | ||||
|             }); | ||||
| 
 | ||||
|         services.AddDbContext<IntegrationEventLogContext>(options => { | ||||
|         services.AddDbContext<IntegrationEventLogContext>(options => | ||||
|         { | ||||
|             options.UseSqlServer(configuration["ConnectionString"], | ||||
|                                     sqlServerOptionsAction: sqlOptions => { | ||||
|                                     sqlServerOptionsAction: sqlOptions => | ||||
|                                     { | ||||
|                                         sqlOptions.MigrationsAssembly(typeof(Program).GetTypeInfo().Assembly.GetName().Name); | ||||
|                                         //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency  | ||||
|                                         sqlOptions.EnableRetryOnFailure(maxRetryCount: 15, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null); | ||||
| @ -218,17 +251,22 @@ public static class CustomExtensionMethods { | ||||
|         return services; | ||||
|     } | ||||
| 
 | ||||
|     public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration) { | ||||
|     public static IServiceCollection AddCustomOptions(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         services.Configure<CatalogSettings>(configuration); | ||||
|         services.Configure<ApiBehaviorOptions>(options => { | ||||
|             options.InvalidModelStateResponseFactory = context => { | ||||
|                 var problemDetails = new ValidationProblemDetails(context.ModelState) { | ||||
|         services.Configure<ApiBehaviorOptions>(options => | ||||
|         { | ||||
|             options.InvalidModelStateResponseFactory = context => | ||||
|             { | ||||
|                 var problemDetails = new ValidationProblemDetails(context.ModelState) | ||||
|                 { | ||||
|                     Instance = context.HttpContext.Request.Path, | ||||
|                     Status = StatusCodes.Status400BadRequest, | ||||
|                     Detail = "Please refer to the errors property for additional details." | ||||
|                 }; | ||||
| 
 | ||||
|                 return new BadRequestObjectResult(problemDetails) { | ||||
|                 return new BadRequestObjectResult(problemDetails) | ||||
|                 { | ||||
|                     ContentTypes = { "application/problem+json", "application/problem+xml" } | ||||
|                 }; | ||||
|             }; | ||||
| @ -237,9 +275,12 @@ public static class CustomExtensionMethods { | ||||
|         return services; | ||||
|     } | ||||
| 
 | ||||
|     public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) { | ||||
|         services.AddSwaggerGen(options => { | ||||
|             options.SwaggerDoc("v1", new OpenApiInfo { | ||||
|     public static IServiceCollection AddSwagger(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         services.AddSwaggerGen(options => | ||||
|         { | ||||
|             options.SwaggerDoc("v1", new OpenApiInfo | ||||
|             { | ||||
|                 Title = "eShopOnContainers - Catalog HTTP API", | ||||
|                 Version = "v1", | ||||
|                 Description = "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample" | ||||
| @ -250,40 +291,49 @@ public static class CustomExtensionMethods { | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) { | ||||
|     public static IServiceCollection AddIntegrationServices(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>( | ||||
|             sp => (DbConnection c) => new IntegrationEventLogService(c)); | ||||
| 
 | ||||
|         services.AddTransient<ICatalogIntegrationEventService, CatalogIntegrationEventService>(); | ||||
| 
 | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) { | ||||
|             services.AddSingleton<IServiceBusPersisterConnection>(sp => { | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) | ||||
|         { | ||||
|             services.AddSingleton<IServiceBusPersisterConnection>(sp => | ||||
|             { | ||||
|                 var settings = sp.GetRequiredService<IOptions<CatalogSettings>>().Value; | ||||
|                 var serviceBusConnection = settings.EventBusConnection; | ||||
| 
 | ||||
|                 return new DefaultServiceBusPersisterConnection(serviceBusConnection); | ||||
|             }); | ||||
|         } | ||||
|         else { | ||||
|             services.AddSingleton<IRabbitMQPersistentConnection>(sp => { | ||||
|         else | ||||
|         { | ||||
|             services.AddSingleton<IRabbitMQPersistentConnection>(sp => | ||||
|             { | ||||
|                 var settings = sp.GetRequiredService<IOptions<CatalogSettings>>().Value; | ||||
|                 var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); | ||||
| 
 | ||||
|                 var factory = new ConnectionFactory() { | ||||
|                 var factory = new ConnectionFactory() | ||||
|                 { | ||||
|                     HostName = configuration["EventBusConnection"], | ||||
|                     DispatchConsumersAsync = true | ||||
|                 }; | ||||
| 
 | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) { | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) | ||||
|                 { | ||||
|                     factory.UserName = configuration["EventBusUserName"]; | ||||
|                 } | ||||
| 
 | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) { | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) | ||||
|                 { | ||||
|                     factory.Password = configuration["EventBusPassword"]; | ||||
|                 } | ||||
| 
 | ||||
|                 var retryCount = 5; | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) { | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) | ||||
|                 { | ||||
|                     retryCount = int.Parse(configuration["EventBusRetryCount"]); | ||||
|                 } | ||||
| 
 | ||||
| @ -294,9 +344,12 @@ public static class CustomExtensionMethods { | ||||
|         return services; | ||||
|     } | ||||
| 
 | ||||
|     public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) { | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) { | ||||
|             services.AddSingleton<IEventBus, EventBusServiceBus>(sp => { | ||||
|     public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) | ||||
|     { | ||||
|         if (configuration.GetValue<bool>("AzureServiceBusEnabled")) | ||||
|         { | ||||
|             services.AddSingleton<IEventBus, EventBusServiceBus>(sp => | ||||
|             { | ||||
|                 var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>(); | ||||
|                 var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>(); | ||||
|                 var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | ||||
| @ -307,15 +360,18 @@ public static class CustomExtensionMethods { | ||||
|             }); | ||||
| 
 | ||||
|         } | ||||
|         else { | ||||
|             services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => { | ||||
|         else | ||||
|         { | ||||
|             services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => | ||||
|             { | ||||
|                 var subscriptionClientName = configuration["SubscriptionClientName"]; | ||||
|                 var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>(); | ||||
|                 var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>(); | ||||
|                 var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | ||||
| 
 | ||||
|                 var retryCount = 5; | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) { | ||||
|                 if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) | ||||
|                 { | ||||
|                     retryCount = int.Parse(configuration["EventBusRetryCount"]); | ||||
|                 } | ||||
| 
 | ||||
|  | ||||
| @ -36,10 +36,12 @@ namespace Ordering.BackgroundTasks.Services | ||||
|                 _logger.LogDebug("GracePeriodManagerService background task is doing background work."); | ||||
| 
 | ||||
|                 CheckConfirmedGracePeriodOrders(); | ||||
|                 try { | ||||
|                 try | ||||
|                 { | ||||
|                     await Task.Delay(_settings.CheckUpdateTime, stoppingToken); | ||||
|                 } | ||||
|                 catch (TaskCanceledException exception) { | ||||
|                 catch (TaskCanceledException exception) | ||||
|                 { | ||||
|                     _logger.LogCritical(exception, "TaskCanceledException Error", exception.Message); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user