Skip to content

Commit

Permalink
Legacy - Mediator Behaviors, Entities, Domain proj (2024-06-20) (#44)
Browse files Browse the repository at this point in the history
* added Legacy Domain project as dependency 🫠

* standard mediator pipeline behaviors

* migrate data command, cmd response, and behavior

* every domain has a constants file, right, right!?

* removed migrations

* entity changes

* introduced Promotion + config

* further Legacy entity changes

* further Legacy changes!

* chores; relational/EF Core fixes, disabled data seeding for now
  • Loading branch information
erikshafer authored Jun 21, 2024
1 parent fd16213 commit 717c943
Show file tree
Hide file tree
Showing 41 changed files with 469 additions and 1,431 deletions.
7 changes: 7 additions & 0 deletions EventSourcingEcommerce.sln
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoppingCart", "src\Retail\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShoppingCart.Api", "src\Retail\ShoppingCart.Api\ShoppingCart.Api.csproj", "{99ECE0F8-DE98-4A6E-84D9-010BAABDACC9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Legacy.Domain", "src\Legacy\Legacy.Domain\Legacy.Domain.csproj", "{80CEA321-B1F7-49F2-B4C0-6A41DC539BD4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -127,6 +129,10 @@ Global
{99ECE0F8-DE98-4A6E-84D9-010BAABDACC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99ECE0F8-DE98-4A6E-84D9-010BAABDACC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99ECE0F8-DE98-4A6E-84D9-010BAABDACC9}.Release|Any CPU.Build.0 = Release|Any CPU
{80CEA321-B1F7-49F2-B4C0-6A41DC539BD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{80CEA321-B1F7-49F2-B4C0-6A41DC539BD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{80CEA321-B1F7-49F2-B4C0-6A41DC539BD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{80CEA321-B1F7-49F2-B4C0-6A41DC539BD4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{9CD0617F-6555-4F29-9C3E-211DC9A92CD5} = {5C748417-563A-41A4-AC92-67A815C5A929}
Expand All @@ -146,5 +152,6 @@ Global
{3C54979E-C2BB-448E-86EE-08F366B973DF} = {5C748417-563A-41A4-AC92-67A815C5A929}
{4280FEC2-9CB2-48B2-B565-17E81AF40333} = {91DC34A2-E5DC-4BDD-9BAE-6B9D1E8E0769}
{99ECE0F8-DE98-4A6E-84D9-010BAABDACC9} = {91DC34A2-E5DC-4BDD-9BAE-6B9D1E8E0769}
{80CEA321-B1F7-49F2-B4C0-6A41DC539BD4} = {920605B8-81CA-4D01-B404-6A83E995FE6D}
EndGlobalSection
EndGlobal
23 changes: 23 additions & 0 deletions src/Legacy/Legacy.Api/Infrastructure/Behaviors/LoggingBehavior.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using MediatR.Pipeline;

namespace Legacy.Api.Infrastructure.Behaviors;

public class LoggingBehavior<TRequest> : IRequestPreProcessor<TRequest>
where TRequest : notnull
{
private readonly ILogger<TRequest> _logger;

public LoggingBehavior(ILoggerFactory logger)
{
_logger = logger.CreateLogger<TRequest>();
}

public Task Process(TRequest request, CancellationToken ct)
{
var requestName = typeof(TRequest).Name;

_logger.LogInformation("Request: {Name} {@Request}", requestName, request);

return Task.CompletedTask;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.Diagnostics;
using MediatR;

namespace Legacy.Api.Infrastructure.Behaviors;

public class PerformanceBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
private readonly ILogger<TRequest> _logger;
private readonly Stopwatch _timer;

public PerformanceBehavior(ILoggerFactory logger)
{
_logger = logger.CreateLogger<TRequest>();
_timer = new Stopwatch();
}

public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken ct)
{
_timer.Start();

var response = await next();

_timer.Stop();

var elapsedMilliseconds = _timer.ElapsedMilliseconds;

if (elapsedMilliseconds <= 500)
return response;

var requestName = typeof(TRequest).Name;

_logger.LogWarning("Long Running Request: {Name} ({ElapsedMilliseconds} milliseconds) {@Request}",
requestName, elapsedMilliseconds, request);

return response;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using MediatR;

namespace Legacy.Api.Infrastructure.Behaviors;

public class UnhandledExceptionBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : notnull
{
private readonly ILogger<TRequest> _logger;

public UnhandledExceptionBehavior(ILoggerFactory logger)
{
_logger = logger.CreateLogger<TRequest>();
}

public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken ct)
{
try
{
return await next();
}
catch (Exception ex)
{
var requestName = typeof(TRequest).Name;

_logger.LogError(ex,
"Request: Unhandled Exception for Request {Name} {@Request}",
requestName, request);

throw;
}
}
}
15 changes: 7 additions & 8 deletions src/Legacy/Legacy.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,15 @@
endpoints.MapControllers();
});

// if(app.Environment.IsDevelopment())
using var scope = app.Services.CreateScope();

var db = scope.ServiceProvider.GetRequiredService<CatalogDbContext>();
db.Database.EnsureDeleted();
db.Database.EnsureCreated();

// db.Database.Migrate(); // migrate

db.Seed(); // seed catalog data
/* database migrations and data seeding */
var catalogDb = scope.ServiceProvider.GetRequiredService<CatalogDbContext>();
catalogDb.Database.EnsureDeleted();
catalogDb.Database.EnsureCreated();
// catalogDb.Seed();
var inventoryDb = scope.ServiceProvider.GetRequiredService<InventoryDbContext>();
// inventoryDb.Seed();

await app.RunAsync();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace Legacy.Api.UseCases.Database;

public record MigrateDataResponse();
10 changes: 10 additions & 0 deletions src/Legacy/Legacy.Api/UseCases/Database/MigrateDatabaseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using MediatR;

namespace Legacy.Api.UseCases.Database;

public record MigrateDatabaseCommand : IRequest<MigrateDataResponse>
{
public static Func<IMediator, Task<MigrateDataResponse>> EndpointHandler
=> mediator
=> mediator.Send(new MigrateDatabaseCommand());
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Legacy.Data.DbContexts;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Legacy.Api.UseCases.Database;

public class MigrateDatabaseCommandHandler : IRequestHandler<MigrateDatabaseCommand, MigrateDataResponse>
{
private readonly CatalogDbContext _catalogDbContext;
private readonly InventoryDbContext _inventoryDbContext;
private readonly ListingDbContext _listingDbContext;
private readonly OrderingDbContext _orderingDbContext;

public MigrateDatabaseCommandHandler(
CatalogDbContext catalogDbContext,
InventoryDbContext inventoryDbContext,
ListingDbContext listingDbContext,
OrderingDbContext orderingDbContext)
{
_catalogDbContext = catalogDbContext;
_inventoryDbContext = inventoryDbContext;
_listingDbContext = listingDbContext;
_orderingDbContext = orderingDbContext;
}

public async Task<MigrateDataResponse> Handle(MigrateDatabaseCommand command, CancellationToken ct)
{
await _catalogDbContext.Database.MigrateAsync(ct);
await _inventoryDbContext.Database.MigrateAsync(ct);
await _listingDbContext.Database.MigrateAsync(ct);
await _orderingDbContext.Database.MigrateAsync(ct);

return new MigrateDataResponse();
}
}
1 change: 1 addition & 0 deletions src/Legacy/Legacy.Application/Legacy.Application.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

<ItemGroup>
<ProjectReference Include="..\Legacy.Data\Legacy.Data.csproj" />
<ProjectReference Include="..\Legacy.Domain\Legacy.Domain.csproj" />
</ItemGroup>

</Project>
5 changes: 3 additions & 2 deletions src/Legacy/Legacy.Data/Configurations/AddressConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ public void Configure(EntityTypeBuilder<Address> builder)
.HasMaxLength(255);

builder.Property(e => e.CountryId);

builder.HasOne<Country>(e => e.Country);
builder.HasOne<Country>(e => e.Country)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);;

builder.Property(e => e.Phone)
.IsRequired(false)
Expand Down
23 changes: 23 additions & 0 deletions src/Legacy/Legacy.Data/Configurations/CartConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Legacy.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Legacy.Data.Configurations;

public class CartConfig : IEntityTypeConfiguration<Cart>
{
public void Configure(EntityTypeBuilder<Cart> builder)
{
builder.HasKey(e => e.Id);

builder.Property(e => e.IsLocked)
.IsRequired(true)
.HasDefaultValue(false);

builder.Property(e => e.CustomerId);
builder.HasOne<Customer>(e => e.Customer);

builder.Property(e => e.DeliveryAddressId);
builder.HasOne<Address>(e => e.DeliveryAddress);
}
}
35 changes: 35 additions & 0 deletions src/Legacy/Legacy.Data/Configurations/CustomerConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Legacy.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Legacy.Data.Configurations;

public class CustomerConfig : IEntityTypeConfiguration<Customer>
{
public void Configure(EntityTypeBuilder<Customer> builder)
{
builder.HasKey(e => e.Id);

builder.Property(e => e.FirstName)
.IsRequired()
.HasMaxLength(128);

builder.Property(e => e.LastName)
.IsRequired()
.HasMaxLength(128);

builder.Property(e => e.Email)
.IsRequired()
.HasMaxLength(255);

builder.Property(e => e.ShippingAddressId);
builder.HasOne<Address>(e => e.ShippingAddress)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);;

builder.Property(e => e.BillingAddressId);
builder.HasOne<Address>(e => e.BillingAddress)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);;
}
}
2 changes: 2 additions & 0 deletions src/Legacy/Legacy.Data/Configurations/InventoryConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class InventoryConfig : IEntityTypeConfiguration<Inventory>
{
public void Configure(EntityTypeBuilder<Inventory> builder)
{
builder.ToTable("Inventories");

builder.HasKey(e => e.Id);

builder.Property(e => e.ItemId);
Expand Down
6 changes: 2 additions & 4 deletions src/Legacy/Legacy.Data/Configurations/ListingConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ public void Configure(EntityTypeBuilder<Listing> builder)
{
builder.HasKey(e => e.Id);

builder.HasOne<Item>();

builder.Property(e => e.ItemId)
.IsRequired();

builder.HasOne<Marketplace>();
builder.HasOne<Item>(e => e.Item);

builder.Property(e => e.MarketplaceId)
.IsRequired();
builder.HasOne<Marketplace>(e => e.Marketplace);

builder.Property(e => e.IsActive)
.IsRequired()
Expand Down
8 changes: 8 additions & 0 deletions src/Legacy/Legacy.Data/Configurations/PaymentConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,13 @@ public void Configure(EntityTypeBuilder<Payment> builder)
builder.Property(e => e.Completed)
.IsRequired()
.HasDefaultValue(false);

builder.Property(e => e.CustomerId);
builder.HasOne<Customer>(e => e.Customer);

builder.Property(e => e.TotalAmount)
.IsRequired()
.HasPrecision(12, 10);

}
}
17 changes: 17 additions & 0 deletions src/Legacy/Legacy.Data/Configurations/PromotionConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Legacy.Data.Entities;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;

namespace Legacy.Data.Configurations;

public class PromotionConfig : IEntityTypeConfiguration<Promotion>
{
public void Configure(EntityTypeBuilder<Promotion> builder)
{
builder.HasKey(e => e.Id);


builder.Property(e => e.ClaimedByCustomerId);
builder.HasOne<Customer>(e => e.ClaimedByCustomer);
}
}
5 changes: 3 additions & 2 deletions src/Legacy/Legacy.Data/Configurations/WarehouseConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ public void Configure(EntityTypeBuilder<Warehouse> builder)
.HasMaxLength(64);

builder.Property(e => e.AddressId);

builder.HasOne<Address>(e => e.Address);
builder.HasOne<Address>(e => e.Address)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);;
}
}
7 changes: 2 additions & 5 deletions src/Legacy/Legacy.Data/DbContexts/CatalogDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@ public CatalogDbContext()
}

public DbSet<Item> Items { get; set; } = default!;

public DbSet<Brand> Brands { get; set; } = default!;

public DbSet<Category> Categories { get; set; } = default!;

public DbSet<Restriction> Restrictions { get; set; } = default!;

public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
public override Task<int> SaveChangesAsync(CancellationToken ct = new())
{
var now = DateTime.UtcNow;

Expand All @@ -40,7 +37,7 @@ public CatalogDbContext()
}
}

return base.SaveChangesAsync(cancellationToken);
return base.SaveChangesAsync(ct);
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
Expand Down
Loading

0 comments on commit 717c943

Please sign in to comment.