@ -1,119 +1,25 @@ | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ; | |||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus; | |||
using Microsoft.Extensions.Diagnostics.HealthChecks; | |||
using RabbitMQ.Client; | |||
namespace Ordering.BackgroundTasks.Extensions; | |||
namespace Ordering.BackgroundTasks.Extensions | |||
public static class CustomExtensionMethods | |||
{ | |||
public static class CustomExtensionMethods | |||
public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
public static IServiceCollection AddCustomHealthCheck(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
var hcBuilder = services.AddHealthChecks(); | |||
hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()); | |||
hcBuilder.AddSqlServer( | |||
configuration["ConnectionString"], | |||
name: "OrderingTaskDB-check", | |||
tags: new string[] { "orderingtaskdb" }); | |||
var hcBuilder = services.AddHealthChecks(); | |||
if (configuration.GetValue<bool>("AzureServiceBusEnabled")) | |||
{ | |||
hcBuilder.AddAzureServiceBusTopic( | |||
configuration["EventBusConnection"], | |||
topicName: "eshop_event_bus", | |||
name: "orderingtask-servicebus-check", | |||
tags: new string[] { "servicebus" }); | |||
} | |||
else | |||
{ | |||
hcBuilder.AddRabbitMQ( | |||
$"amqp://{configuration["EventBusConnection"]}", | |||
name: "orderingtask-rabbitmqbus-check", | |||
tags: new string[] { "rabbitmqbus" }); | |||
} | |||
hcBuilder.AddSqlServer(_ => | |||
configuration.GetRequiredConnectionString("OrderingDb"), | |||
name: "OrderingTaskDB-check", | |||
tags: new string[] { "live", "ready" }); | |||
return services; | |||
} | |||
return services; | |||
} | |||
public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) | |||
public static IServiceCollection AddApplicationOptions(this IServiceCollection services, IConfiguration configuration) | |||
{ | |||
return services.Configure<BackgroundTaskSettings>(configuration) | |||
.Configure<BackgroundTaskSettings>(o => | |||
{ | |||
var subscriptionClientName = configuration["SubscriptionClientName"]; | |||
if (configuration.GetValue<bool>("AzureServiceBusEnabled")) | |||
{ | |||
services.AddSingleton<IServiceBusPersisterConnection>(sp => | |||
{ | |||
var serviceBusConnectionString = configuration["EventBusConnection"]; | |||
return new DefaultServiceBusPersisterConnection(serviceBusConnectionString); | |||
}); | |||
services.AddSingleton<IEventBus, EventBusServiceBus>(sp => | |||
{ | |||
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>(); | |||
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>(); | |||
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | |||
string subscriptionName = configuration["SubscriptionClientName"]; | |||
return new EventBusServiceBus(serviceBusPersisterConnection, logger, eventBusSubcriptionsManager, sp, subscriptionName); | |||
}); | |||
} | |||
else | |||
{ | |||
services.AddSingleton<IRabbitMQPersistentConnection>(sp => | |||
{ | |||
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>(); | |||
var factory = new ConnectionFactory() | |||
{ | |||
HostName = configuration["EventBusConnection"], | |||
DispatchConsumersAsync = true | |||
}; | |||
if (!string.IsNullOrEmpty(configuration["EventBusUserName"])) | |||
{ | |||
factory.UserName = configuration["EventBusUserName"]; | |||
} | |||
if (!string.IsNullOrEmpty(configuration["EventBusPassword"])) | |||
{ | |||
factory.Password = configuration["EventBusPassword"]; | |||
} | |||
var retryCount = 5; | |||
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) | |||
{ | |||
retryCount = int.Parse(configuration["EventBusRetryCount"]); | |||
} | |||
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount); | |||
}); | |||
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp => | |||
{ | |||
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>(); | |||
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>(); | |||
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); | |||
var retryCount = 5; | |||
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"])) | |||
{ | |||
retryCount = int.Parse(configuration["EventBusRetryCount"]); | |||
} | |||
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, sp, eventBusSubcriptionsManager, subscriptionClientName, retryCount); | |||
}); | |||
} | |||
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>(); | |||
return services; | |||
} | |||
o.ConnectionString = configuration.GetRequiredConnectionString("OrderingDb"); | |||
}); | |||
} | |||
} |
@ -1,13 +1,10 @@ | |||
global using Microsoft.AspNetCore.Hosting; | |||
global using Microsoft.Extensions.Configuration; | |||
global using Microsoft.Extensions.Hosting; | |||
global using Ordering.BackgroundTasks.Extensions; | |||
global using System.IO; | |||
global using HealthChecks.UI.Client; | |||
global using System; | |||
global using Microsoft.AspNetCore.Builder; | |||
global using Microsoft.AspNetCore.Diagnostics.HealthChecks; | |||
global using Microsoft.Extensions.Configuration; | |||
global using Microsoft.Extensions.DependencyInjection; | |||
global using Microsoft.Extensions.Hosting; | |||
global using Microsoft.Extensions.Logging; | |||
global using Ordering.BackgroundTasks.Services; | |||
global using System; | |||
global using Ordering.BackgroundTasks; | |||
global using Ordering.BackgroundTasks.Extensions; | |||
global using Ordering.BackgroundTasks.Services; | |||
global using Services.Common; |
@ -1,32 +1,18 @@ | |||
var builder = WebApplication.CreateBuilder(new WebApplicationOptions | |||
{ | |||
Args = args, | |||
ApplicationName = typeof(Program).Assembly.FullName | |||
}); | |||
builder.Configuration.SetBasePath(Directory.GetCurrentDirectory()); | |||
builder.Configuration.AddJsonFile("appsettings.json", optional: true); | |||
builder.Configuration.AddJsonFile($"appsettings.{builder.Environment.EnvironmentName}.json", optional: true); | |||
builder.Configuration.AddEnvironmentVariables(); | |||
builder.Services.AddCustomHealthCheck(builder.Configuration) | |||
.Configure<BackgroundTaskSettings>(builder.Configuration) | |||
.AddHostedService<GracePeriodManagerService>() | |||
.AddEventBus(builder.Configuration); | |||
var builder = WebApplication.CreateBuilder(args); | |||
builder.AddServiceDefaults(); | |||
builder.Services.AddHealthChecks(builder.Configuration); | |||
builder.Services.AddApplicationOptions(builder.Configuration); | |||
builder.Services.AddHostedService<GracePeriodManagerService>(); | |||
var app = builder.Build(); | |||
if (!app.Environment.IsDevelopment()) | |||
if (!await app.CheckHealthAsync()) | |||
{ | |||
app.UseExceptionHandler("/Home/Error"); | |||
return; | |||
} | |||
app.UseRouting(); | |||
app.MapHealthChecks("/hc", new HealthCheckOptions() | |||
{ | |||
Predicate = _ => true, | |||
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse | |||
}); | |||
app.MapHealthChecks("/liveness", new HealthCheckOptions | |||
{ | |||
Predicate = r => r.Name.Contains("self") | |||
}); | |||
app.UseServiceDefaults(); | |||
await app.RunAsync(); |
@ -1,14 +1,17 @@ | |||
{ | |||
"ConnectionString": "Server=tcp:127.0.0.1,5433;Database=Microsoft.eShopOnContainers.Services.OrderingDb;User Id=sa;Password=Pass@word;", | |||
"SubscriptionClientName": "BackgroundTasks", | |||
"GracePeriodTime": "1", | |||
"CheckUpdateTime": "1000", | |||
"ApplicationInsights": { | |||
"InstrumentationKey": "" | |||
"Logging": { | |||
"LogLevel": { | |||
"Default": "Information", | |||
"Microsoft.AspNetCore": "Warning" | |||
} | |||
}, | |||
"ConnectionStrings": { | |||
"EventBus": "localhost" | |||
}, | |||
"AzureServiceBusEnabled": false, | |||
"EventBusRetryCount": 5, | |||
"EventBusConnection": "", | |||
"EventBusUserName": "", | |||
"EventBusPassword": "" | |||
"EventBus": { | |||
"SubscriptionClientName": "BackgroundTasks", | |||
"RetryCount": 5 | |||
}, | |||
"GracePeriodTime": "1", | |||
"CheckUpdateTime": "1000" | |||
} |
@ -1,16 +1,17 @@ | |||
global using Microsoft.AspNetCore.Authentication.JwtBearer; | |||
global using System; | |||
global using System.Collections.Generic; | |||
global using System.Threading.Tasks; | |||
global using Microsoft.AspNetCore.Authentication.JwtBearer; | |||
global using Microsoft.AspNetCore.Authorization; | |||
global using Microsoft.AspNetCore.Builder; | |||
global using Microsoft.AspNetCore.SignalR; | |||
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; | |||
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; | |||
global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; | |||
global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub; | |||
global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents; | |||
global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; | |||
global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.Events; | |||
global using Microsoft.Extensions.Configuration; | |||
global using Microsoft.Extensions.DependencyInjection; | |||
global using Microsoft.Extensions.Logging; | |||
global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub.IntegrationEvents.EventHandling; | |||
global using Microsoft.eShopOnContainers.Services.Ordering.SignalrHub; | |||
global using System.Collections.Generic; | |||
global using System.Threading.Tasks; | |||
global using System; | |||
global using Services.Common; |
@ -0,0 +1,10 @@ | |||
namespace Microsoft.Extensions.Configuration; | |||
public static class ConfigurationExtensions | |||
{ | |||
public static string GetRequiredValue(this IConfiguration configuration, string name) => | |||
configuration[name] ?? throw new InvalidOperationException($"Configuration missing value for: {(configuration is IConfigurationSection s ? s.Path + ":" + name : name)}"); | |||
public static string GetRequiredConnectionString(this IConfiguration configuration, string name) => | |||
configuration.GetConnectionString(name) ?? throw new InvalidOperationException($"Configuration missing value for: {(configuration is IConfigurationSection s ? s.Path + ":ConnectionStrings:" + name : "ConnectionStrings:" + name)}"); | |||
} |