Browse Source

Updated background tasks to use common service logic

davidfowl/common-services
David Fowler 1 year ago
committed by Reuben Bond
parent
commit
c41cd3830c
14 changed files with 73 additions and 184 deletions
  1. +2
    -2
      src/Services/Basket/Basket.API/CustomExtensionMethods.cs
  2. +1
    -4
      src/Services/Catalog/Catalog.API/CustomExtensionMethods.cs
  3. +0
    -3
      src/Services/Ordering/Ordering.API/CustomExtensionsMethods.cs
  4. +1
    -0
      src/Services/Ordering/Ordering.API/GlobalUsings.cs
  5. +1
    -3
      src/Services/Ordering/Ordering.API/Program.cs
  6. +16
    -110
      src/Services/Ordering/Ordering.BackgroundTasks/Extensions/CustomExtensionMethods.cs
  7. +6
    -9
      src/Services/Ordering/Ordering.BackgroundTasks/GlobalUsings.cs
  8. +1
    -0
      src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj
  9. +12
    -26
      src/Services/Ordering/Ordering.BackgroundTasks/Program.cs
  10. +14
    -11
      src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json
  11. +8
    -7
      src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs
  12. +1
    -3
      src/Services/Ordering/Ordering.SignalrHub/Program.cs
  13. +0
    -6
      src/Services/Services.Common/CommonExtensions.cs
  14. +10
    -0
      src/Services/Services.Common/ConfigurationExtensions.cs

+ 2
- 2
src/Services/Basket/Basket.API/CustomExtensionMethods.cs View File

@ -5,7 +5,7 @@ public static class CustomExtensionMethods
public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddHealthChecks() services.AddHealthChecks()
.AddRedis(_ => configuration.GetConnectionString("redis"), "redis", tags: new[] { "ready", "liveness" });
.AddRedis(_ => configuration.GetRequiredConnectionString("redis"), "redis", tags: new[] { "ready", "liveness" });
return services; return services;
} }
@ -14,7 +14,7 @@ public static class CustomExtensionMethods
{ {
return services.AddSingleton(sp => return services.AddSingleton(sp =>
{ {
var redisConfig = ConfigurationOptions.Parse(configuration.GetConnectionString("redis"), true);
var redisConfig = ConfigurationOptions.Parse(configuration.GetRequiredConnectionString("redis"), true);
return ConnectionMultiplexer.Connect(redisConfig); return ConnectionMultiplexer.Connect(redisConfig);
}); });


+ 1
- 4
src/Services/Catalog/Catalog.API/CustomExtensionMethods.cs View File

@ -7,7 +7,7 @@ public static class CustomExtensionMethods
var hcBuilder = services.AddHealthChecks(); var hcBuilder = services.AddHealthChecks();
hcBuilder hcBuilder
.AddSqlServer(_ => configuration.GetConnectionString("CatalogDB"),
.AddSqlServer(_ => configuration.GetRequiredConnectionString("CatalogDB"),
name: "CatalogDB-check", name: "CatalogDB-check",
tags: new string[] { "live", "ready" }); tags: new string[] { "live", "ready" });
@ -89,7 +89,4 @@ public static class CustomExtensionMethods
return services; return services;
} }
private 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)}");
} }

+ 0
- 3
src/Services/Ordering/Ordering.API/CustomExtensionsMethods.cs View File

@ -73,7 +73,4 @@ static class CustomExtensionsMethods
return services; return services;
} }
private 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)}");
} }

+ 1
- 0
src/Services/Ordering/Ordering.API/GlobalUsings.cs View File

@ -52,6 +52,7 @@ global using Microsoft.Extensions.Logging;
global using Microsoft.Extensions.Options; global using Microsoft.Extensions.Options;
global using Polly; global using Polly;
global using Polly.Retry; global using Polly.Retry;
global using Services.Common;
global using Swashbuckle.AspNetCore.SwaggerGen; global using Swashbuckle.AspNetCore.SwaggerGen;
global using AppCommand = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; global using AppCommand = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
global using ApiModels = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models; global using ApiModels = Microsoft.eShopOnContainers.Services.Ordering.API.Application.Models;

+ 1
- 3
src/Services/Ordering/Ordering.API/Program.cs View File

@ -1,6 +1,4 @@
using Services.Common;
var builder = WebApplication.CreateBuilder(args);
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults(); builder.AddServiceDefaults();


+ 16
- 110
src/Services/Ordering/Ordering.BackgroundTasks/Extensions/CustomExtensionMethods.cs View File

@ -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");
});
} }
} }

+ 6
- 9
src/Services/Ordering/Ordering.BackgroundTasks/GlobalUsings.cs View File

@ -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.Builder;
global using Microsoft.AspNetCore.Diagnostics.HealthChecks;
global using Microsoft.Extensions.Configuration;
global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Hosting;
global using Microsoft.Extensions.Logging; global using Microsoft.Extensions.Logging;
global using Ordering.BackgroundTasks.Services;
global using System;
global using Ordering.BackgroundTasks; global using Ordering.BackgroundTasks;
global using Ordering.BackgroundTasks.Extensions;
global using Ordering.BackgroundTasks.Services;
global using Services.Common;

+ 1
- 0
src/Services/Ordering/Ordering.BackgroundTasks/Ordering.BackgroundTasks.csproj View File

@ -23,5 +23,6 @@
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
<ProjectReference Include="..\..\Services.Common\Services.Common.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

+ 12
- 26
src/Services/Ordering/Ordering.BackgroundTasks/Program.cs View File

@ -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(); 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(); await app.RunAsync();

+ 14
- 11
src/Services/Ordering/Ordering.BackgroundTasks/appsettings.json View File

@ -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"
} }

+ 8
- 7
src/Services/Ordering/Ordering.SignalrHub/GlobalUsings.cs View File

@ -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.Authorization;
global using Microsoft.AspNetCore.Builder; global using Microsoft.AspNetCore.Builder;
global using Microsoft.AspNetCore.SignalR; global using Microsoft.AspNetCore.SignalR;
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
global using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; 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;
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.Configuration;
global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.DependencyInjection;
global using Microsoft.Extensions.Logging; 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;

+ 1
- 3
src/Services/Ordering/Ordering.SignalrHub/Program.cs View File

@ -1,6 +1,4 @@
using Services.Common;
var builder = WebApplication.CreateBuilder(args);
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults(); builder.AddServiceDefaults();


+ 0
- 6
src/Services/Services.Common/CommonExtensions.cs View File

@ -419,10 +419,4 @@ public static class CommonExtensions
Predicate = r => r.Name.Contains("self") Predicate = r => r.Name.Contains("self")
}); });
} }
private 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)}");
private 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)}");
} }

+ 10
- 0
src/Services/Services.Common/ConfigurationExtensions.cs View File

@ -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)}");
}

Loading…
Cancel
Save