Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f44acd8c82 |
@@ -9,7 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using LiteCharms.Features.Models;
|
||||
using LiteCharms.Features.Shop.Notifications;
|
||||
using LiteCharms.Features.Shop.Notifications.Events;
|
||||
using static LiteCharms.Features.Extensions.Email;
|
||||
|
||||
namespace LiteCharms.Features.Tests;
|
||||
|
||||
@@ -21,8 +20,8 @@ public class NotificationsFeatureTests(CommonFixture fixture, ITestOutputHelper
|
||||
Priority = Shop.Priorities.Medium,
|
||||
Sender = "xUnit Test",
|
||||
SenderAddress = "khwezi@mngoma.africa",
|
||||
Recipient = $"{ShopEmailFromName} [Test]",
|
||||
RecipientAddress = ShopEmailFromAddress,
|
||||
Recipient = $"{Email.Extensions.Constants.ShopEmailFromName} [Test]",
|
||||
RecipientAddress = Email.Extensions.Constants.ShopEmailFromAddress,
|
||||
Subject = "Test Message",
|
||||
Message = "This is an automation test",
|
||||
IsHtml = false,
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
using LiteCharms.Features.Shop.Products;
|
||||
|
||||
namespace LiteCharms.Features.Tests;
|
||||
|
||||
public class ProductsFeatureTests(CommonFixture fixture, ITestOutputHelper output) : IClassFixture<CommonFixture>
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetProductsAsync_ReturnsProducts()
|
||||
{
|
||||
var productService = fixture.Services.GetRequiredService<ProductService>();
|
||||
|
||||
var result = await productService.GetProductsAsync();
|
||||
|
||||
Assert.True(result.IsSuccess);
|
||||
Assert.NotNull(result.Value);
|
||||
|
||||
output.WriteLine($"Retrieved {result.Value.Length} products.");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using LiteCharms.Features.Shop;
|
||||
using LiteCharms.Features.Shop.Notifications;
|
||||
using static LiteCharms.Features.Extensions.Email;
|
||||
using static LiteCharms.Features.Email.Extensions.Constants;
|
||||
|
||||
namespace LiteCharms.Features.Email.Events.Handlers;
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace LiteCharms.Features.Email.Extensions;
|
||||
|
||||
public static class Constants
|
||||
{
|
||||
public const string ShopSchedulerName = "shop";
|
||||
public const string ShopEmailFromName = "Khongisa Shop";
|
||||
public const string ShopEmailFromAddress = "shop@litecharms.co.za";
|
||||
}
|
||||
@@ -4,10 +4,7 @@ using LiteCharms.Features.Email.Configuration;
|
||||
namespace LiteCharms.Features.Extensions;
|
||||
|
||||
public static class Email
|
||||
{
|
||||
public const string ShopEmailFromName = "Khongisa Shop";
|
||||
public const string ShopEmailFromAddress = "shop@litecharms.co.za";
|
||||
|
||||
{
|
||||
public static IServiceCollection AddEmailServices(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.Configure<SmtpSettings>(configuration.GetSection("Email"));
|
||||
|
||||
@@ -1,34 +1,19 @@
|
||||
using LiteCharms.Features.HealthChecks;
|
||||
using static LiteCharms.Features.Extensions.Postgres;
|
||||
|
||||
namespace LiteCharms.Features.Extensions;
|
||||
|
||||
public static class HealthChecks
|
||||
{
|
||||
public static IServiceCollection AddShopQuartzHealthCheck(this IServiceCollection services)
|
||||
public static IServiceCollection AddQuartzHealtchCheck(this IServiceCollection services)
|
||||
{
|
||||
services.AddHealthChecks().AddCheck<ShopQuartzHealthCheck>("ShopQuartz");
|
||||
services.AddHealthChecks().AddCheck<QuartzHealthCheck>("Quartz");
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddMidrandShopQuartzHealthCheck(this IServiceCollection services)
|
||||
public static IServiceCollection AddPostgresHealtchCheck(this IServiceCollection services)
|
||||
{
|
||||
services.AddHealthChecks().AddCheck<MidrandShopQuartzHealthCheck>("MidrandShopQuartz");
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddShopPostgresHealthCheck(this IServiceCollection services)
|
||||
{
|
||||
services.AddHealthChecks().AddCheck<PostgresShopHealthCheck>(ShopDbConfigName);
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddMidrandShopPostgresHealthCheck(this IServiceCollection services)
|
||||
{
|
||||
services.AddHealthChecks().AddCheck<PostgresMidrandShopHealthCheck>(MidrandShopDbConfigName);
|
||||
services.AddHealthChecks().AddCheck<PostgresHealthCheck>("PostgreSQL");
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -1,26 +1,13 @@
|
||||
using LiteCharms.Features.MidrandShop.Postgres;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
using LiteCharms.Features.Shop.Postgres;
|
||||
|
||||
namespace LiteCharms.Features.Extensions;
|
||||
|
||||
public static class Postgres
|
||||
{
|
||||
public const string MidrandShopDbConfigName = "PostgresMidrandShop";
|
||||
public const string ShopDbConfigName = "PostgresShop";
|
||||
public const string SchedulerDbConfigName = "PostgresScheduler";
|
||||
|
||||
public static IServiceCollection AddShopDatabase(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddPooledDbContextFactory<ShopDbContext>(options =>
|
||||
options.UseNpgsql(configuration.GetConnectionString(ShopDbConfigName)));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddMidrandShopDatabase(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddPooledDbContextFactory<MidrandShopDbContext>(options =>
|
||||
options.UseNpgsql(configuration.GetConnectionString(MidrandShopDbConfigName)));
|
||||
options.UseNpgsql(configuration.GetConnectionString("PostgresShop")));
|
||||
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
using LiteCharms.Features.Quartz;
|
||||
using LiteCharms.Features.Quartz.Abstractions;
|
||||
using static LiteCharms.Features.Extensions.Postgres;
|
||||
|
||||
namespace LiteCharms.Features.Extensions;
|
||||
|
||||
public static class Quartz
|
||||
{
|
||||
public const string ShopSchedulerName = "shop";
|
||||
public const string MidrandShopSchedulerName = "midrandshop";
|
||||
private const string databaseConfigName = "PostgresScheduler";
|
||||
|
||||
public static IServiceCollection AddQuartzSchedulerClient(this IServiceCollection services, string schedulerName, IConfiguration configuration)
|
||||
{
|
||||
var connectionString = configuration.GetConnectionString(SchedulerDbConfigName);
|
||||
var connectionString = configuration.GetConnectionString(databaseConfigName);
|
||||
|
||||
services.ConfigureCommon();
|
||||
|
||||
@@ -46,7 +44,7 @@ public static class Quartz
|
||||
|
||||
public static IServiceCollection AddQuartzScheduler(this IServiceCollection services, string schedulerName, IConfiguration configuration)
|
||||
{
|
||||
var connectionString = configuration.GetConnectionString(SchedulerDbConfigName);
|
||||
var connectionString = configuration.GetConnectionString(databaseConfigName);
|
||||
|
||||
services.ConfigureCommon();
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
using static LiteCharms.Features.Extensions.Quartz;
|
||||
|
||||
namespace LiteCharms.Features.HealthChecks;
|
||||
|
||||
public class MidrandShopQuartzHealthCheck(ISchedulerFactory schedulerFactory) : IHealthCheck
|
||||
{
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var scheduler = await schedulerFactory.GetScheduler(MidrandShopSchedulerName, cancellationToken);
|
||||
|
||||
if(scheduler == null)
|
||||
return HealthCheckResult.Unhealthy($"Scheduler with name '{MidrandShopSchedulerName}' not found.");
|
||||
|
||||
if (!scheduler.IsStarted)
|
||||
return HealthCheckResult.Unhealthy($"{MidrandShopSchedulerName} Quartz scheduler is not running");
|
||||
|
||||
await scheduler.CheckExists(new JobKey(Guid.NewGuid().ToString()), cancellationToken);
|
||||
|
||||
return HealthCheckResult.Healthy($"{MidrandShopSchedulerName} Quartz scheduler is ready");
|
||||
}
|
||||
catch (SchedulerException)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy($"{MidrandShopSchedulerName} Quartz scheduler cannot connect to the store");
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-7
@@ -1,10 +1,8 @@
|
||||
using static LiteCharms.Features.Extensions.Postgres;
|
||||
namespace LiteCharms.Features.HealthChecks;
|
||||
|
||||
namespace LiteCharms.Features.HealthChecks;
|
||||
|
||||
public class PostgresShopHealthCheck(IConfiguration configuration) : IHealthCheck
|
||||
public class PostgresHealthCheck(IConfiguration configuration) : IHealthCheck
|
||||
{
|
||||
private readonly string connectionString = configuration.GetConnectionString(ShopDbConfigName)!;
|
||||
private readonly string connectionString = configuration.GetConnectionString("PostgresShop")!;
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -18,11 +16,11 @@ public class PostgresShopHealthCheck(IConfiguration configuration) : IHealthChec
|
||||
|
||||
await command.ExecuteScalarAsync(cancellationToken);
|
||||
|
||||
return HealthCheckResult.Healthy($"{ShopDbConfigName} is responsive.");
|
||||
return HealthCheckResult.Healthy("PostgreSQL is responsive.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy($"{ShopDbConfigName} is unreachable.", ex);
|
||||
return HealthCheckResult.Unhealthy("PostgreSQL is unreachable.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using static LiteCharms.Features.Extensions.Postgres;
|
||||
|
||||
namespace LiteCharms.Features.HealthChecks;
|
||||
|
||||
public class PostgresMidrandShopHealthCheck(IConfiguration configuration) : IHealthCheck
|
||||
{
|
||||
private readonly string connectionString = configuration.GetConnectionString(MidrandShopDbConfigName)!;
|
||||
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
await using var dataSource = NpgsqlDataSource.Create(connectionString);
|
||||
await using var connection = await dataSource.OpenConnectionAsync(cancellationToken);
|
||||
|
||||
await using var command = connection.CreateCommand();
|
||||
command.CommandText = "SELECT 1";
|
||||
|
||||
await command.ExecuteScalarAsync(cancellationToken);
|
||||
|
||||
return HealthCheckResult.Healthy($"{MidrandShopDbConfigName} is responsive.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy($"{MidrandShopDbConfigName} is unreachable.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace LiteCharms.Features.HealthChecks;
|
||||
|
||||
public class QuartzHealthCheck(ISchedulerFactory schedulerFactory) : IHealthCheck
|
||||
{
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var scheduler = await schedulerFactory.GetScheduler(cancellationToken);
|
||||
|
||||
if (!scheduler.IsStarted)
|
||||
return HealthCheckResult.Unhealthy("Quartz scheduler is not running");
|
||||
|
||||
await scheduler.CheckExists(new JobKey(Guid.NewGuid().ToString()), cancellationToken);
|
||||
|
||||
return HealthCheckResult.Healthy("Quartz scheduler is ready");
|
||||
}
|
||||
catch (SchedulerException)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("Quartz scheduler cannot connect to the store");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using static LiteCharms.Features.Extensions.Quartz;
|
||||
|
||||
namespace LiteCharms.Features.HealthChecks;
|
||||
|
||||
public class ShopQuartzHealthCheck(ISchedulerFactory schedulerFactory) : IHealthCheck
|
||||
{
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
{
|
||||
var scheduler = await schedulerFactory.GetScheduler(ShopSchedulerName, cancellationToken);
|
||||
|
||||
if(scheduler == null)
|
||||
return HealthCheckResult.Unhealthy($"Scheduler with name '{ShopSchedulerName}' not found.");
|
||||
|
||||
if (!scheduler.IsStarted)
|
||||
return HealthCheckResult.Unhealthy($"{ShopSchedulerName} Quartz scheduler is not running");
|
||||
|
||||
await scheduler.CheckExists(new JobKey(Guid.NewGuid().ToString()), cancellationToken);
|
||||
|
||||
return HealthCheckResult.Healthy($"{ShopSchedulerName} Quartz scheduler is ready");
|
||||
}
|
||||
catch (SchedulerException)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy($"{ShopSchedulerName} Quartz scheduler cannot connect to the store");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,8 +131,8 @@
|
||||
|
||||
<!-- Amazon S3 SDK -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AWSSDK.Extensions.NetCore.Setup" Version="4.0.4.1" />
|
||||
<PackageReference Include="AWSSDK.S3" Version="4.0.23.4" />
|
||||
<PackageReference Include="AWSSDK.Extensions.NetCore.Setup" Version="4.0.3.40" />
|
||||
<PackageReference Include="AWSSDK.S3" Version="4.0.23.3" />
|
||||
|
||||
<!-- global Usings -->
|
||||
<Using Include="Amazon.S3" />
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
namespace LiteCharms.Features.MidrandShop.Postgres;
|
||||
|
||||
public class MidrandShopDbContext(DbContextOptions<MidrandShopDbContext> options) : DbContext(options)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
using static LiteCharms.Features.Extensions.Postgres;
|
||||
|
||||
namespace LiteCharms.Features.MidrandShop.Postgres;
|
||||
|
||||
public class MidrandShopDbContextFactory : IDesignTimeDbContextFactory<MidrandShopDbContext>
|
||||
{
|
||||
public MidrandShopDbContext CreateDbContext(string[] args)
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(Directory.GetCurrentDirectory())
|
||||
.AddUserSecrets(typeof(MidrandShopDbContext).Assembly)
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<MidrandShopDbContext>();
|
||||
optionsBuilder.UseNpgsql(configuration.GetConnectionString(MidrandShopDbConfigName));
|
||||
|
||||
return new MidrandShopDbContext(optionsBuilder.Options);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using static LiteCharms.Features.Extensions.Postgres;
|
||||
|
||||
namespace LiteCharms.Features.Shop.Postgres;
|
||||
namespace LiteCharms.Features.Shop.Postgres;
|
||||
|
||||
public class ShopDbContextFactory : IDesignTimeDbContextFactory<ShopDbContext>
|
||||
{
|
||||
@@ -14,7 +12,7 @@ public class ShopDbContextFactory : IDesignTimeDbContextFactory<ShopDbContext>
|
||||
.Build();
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<ShopDbContext>();
|
||||
optionsBuilder.UseNpgsql(configuration.GetConnectionString(ShopDbConfigName));
|
||||
optionsBuilder.UseNpgsql(configuration.GetConnectionString("PostgresShop"));
|
||||
|
||||
return new ShopDbContext(optionsBuilder.Options);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user