From 42750404f266c226181cc053ae951ec6530d139b Mon Sep 17 00:00:00 2001 From: meysamhadeli Date: Sun, 31 Jul 2022 01:39:37 +0430 Subject: [PATCH] refactor persist-message-processor --- booking.rest | 16 +- .../EventBus.Messages/PassengerContracts.cs | 8 +- src/BuildingBlocks/Core/Event/IEvent.cs | 3 +- .../Core/Event/IInternalCommand.cs | 5 + .../Core/Event/IInternalCommnad.cs | 11 - .../Core/Event/InternalCommand.cs | 11 +- src/BuildingBlocks/Core/EventDispatcher.cs | 20 +- src/BuildingBlocks/Core/IEventDispatcher.cs | 4 +- src/BuildingBlocks/Core/IEventMapper.cs | 2 +- src/BuildingBlocks/Core/Model/Aggregate.cs | 4 +- .../Core/Model/{Entity.cs => Audit.cs} | 2 +- src/BuildingBlocks/Core/Model/IAggregate.cs | 2 +- .../Core/Model/{IEntity.cs => IAudit.cs} | 2 +- src/BuildingBlocks/EFCore/AppDbContextBase.cs | 16 +- src/BuildingBlocks/EFCore/EfTxBehavior.cs | 8 +- src/BuildingBlocks/EFCore/Extensions.cs | 7 +- src/BuildingBlocks/EFCore/IDbContext.cs | 4 +- src/BuildingBlocks/EventStoreDB/Config.cs | 5 +- .../Events/AggregateEventSourcing.cs | 6 +- .../Events/IAggregateEventSourcing.cs | 4 +- .../Repository/EventStoreDBRepository.cs | 24 +- .../Repository/RepositoryExtensions.cs | 2 +- .../MassTransit/ConsumeFilter.cs | 2 +- .../PersistMessageProcessor.cs | 208 ---------- .../PersistMessageConfiguration.cs | 7 +- .../Data/DesignTimeDbContextFactory.cs | 16 + .../20220728155556_initial.Designer.cs} | 59 +-- .../Migrations/20220728155556_initial.cs} | 13 +- .../PersistMessageDbContextModelSnapshot.cs | 63 +++ .../Data/PersistMessageDbContext.cs | 23 ++ .../PersistMessageProcessor/Data/readme.md | 2 + .../Extensions.cs | 15 +- .../IPersistMessageDbContext.cs | 9 + .../IPersistMessageProcessor.cs | 10 +- .../MessageDeliveryType.cs | 2 +- .../MessageStatus.cs | 2 +- .../PersistMessage.cs | 8 +- .../PersistMessageBackgroundService.cs | 28 +- .../PersistMessageOptions.cs | 3 +- .../PersistMessageProcessor.cs | 219 +++++++++++ .../TestBase/IntegrationTestBase.cs | 21 +- .../Utils/CurrentUserProvider.cs | 29 ++ src/BuildingBlocks/Utils/TypeProvider.cs | 76 +--- .../Booking/src/Booking.Api/Program.cs | 12 +- .../Booking/src/Booking.Api/appsettings.json | 10 +- .../src/Booking.Api/appsettings.test.json | 7 +- .../Booking/src/Booking/Booking.csproj | 4 - .../Domain/BookingCreatedDomainEvent.cs | 3 +- .../Booking/Features/BookingMappings.cs | 3 + .../CreateBooking/CreateBookingCommand.cs | 3 +- .../CreateBookingCommandHandler.cs | 13 +- .../src/Booking/Booking/Models/Booking.cs | 29 +- .../Booking/Models/Reads/BookingReadModel.cs | 12 + .../Booking/src/Booking/BookingProjection.cs | 29 +- .../src/Booking/Data/BookingDbContext.cs | 23 -- .../src/Booking/Data/BookingReadDbContext.cs | 17 + .../Configurations/BookingConfiguration.cs | 32 -- .../Data/DesignTimeDbContextFactory.cs | 16 - .../20220507150115_initial.Designer.cs | 117 ------ .../Data/Migrations/20220507150115_initial.cs | 50 --- ...0616121920_Add-PersistMessages.Designer.cs | 152 -------- .../BookingDbContextModelSnapshot.cs | 150 -------- .../Booking/src/Booking/Data/readme.md | 2 - .../Booking/src/Booking/EventMapper.cs | 2 +- .../src/Booking/Extensions/CoreExtensions.cs | 17 + .../Booking/Extensions/MediatRExtensions.cs | 1 - .../Booking/Features/CreateBookingTests.cs | 7 +- src/Services/Flight/src/Flight.Api/Program.cs | 5 +- .../Flight/src/Flight.Api/appsettings.json | 3 +- .../src/Flight.Api/appsettings.test.json | 3 +- .../CreateAircraft/CreateAircraftCommand.cs | 1 + .../src/Flight/Aircrafts/Models/Aircraft.cs | 2 +- .../CreateAirport/CreateAirportCommand.cs | 1 + .../Reads/CreateAirportMongoCommand.cs | 1 - .../src/Flight/Airports/Models/Airport.cs | 2 +- .../PersistMessageConfiguration.cs | 43 --- .../Flight/src/Flight/Data/FlightDbContext.cs | 7 +- .../src/Flight/Data/FlightReadDbContext.cs | 1 - ...0616121204_Add-PersistMessages.Designer.cs | 266 ------------- .../20220616121204_Add-PersistMessages.cs | 38 -- ...ner.cs => 20220728175834_Init.Designer.cs} | 2 +- ...1215248_Init.cs => 20220728175834_Init.cs} | 16 +- .../FlightDbContextModelSnapshot.cs | 35 -- src/Services/Flight/src/Flight/EventMapper.cs | 2 +- .../src/Flight/Extensions/CoreExtensions.cs | 17 + .../CreateFlight/CreateFlightCommand.cs | 1 + .../CreateFlightCommandHandler.cs | 2 - .../Reads/CreateFlightMongoCommand.cs | 32 +- .../Reads/CreateFlightMongoCommandHandler.cs | 2 +- .../DeleteFlight/DeleteFlightCommand.cs | 1 + .../Reads/DeleteFlightMongoCommand.cs | 32 +- .../Reads/DeleteFlightMongoCommandHandler.cs | 2 +- .../GetFlightByIdQueryHandler.cs | 3 +- .../Reads/UpdateFlightMongoCommandHandler.cs | 2 +- .../UpdateFlight/UpdateFlightCommand.cs | 1 + .../src/Flight/Flights/Models/Flight.cs | 2 +- .../Flights/Models/Reads/FlightReadModel.cs | 26 +- .../Features/CreateSeat/CreateSeatCommand.cs | 1 + .../GetAvailableSeatsQueryHandler.cs | 2 +- .../Reads/ReserveSeatMongoCommand.cs | 1 - .../ReserveSeat/ReserveSeatCommand.cs | 1 + .../Flight/src/Flight/Seats/Models/Seat.cs | 2 +- .../tests/UnitTest/Common/DbContextFactory.cs | 2 +- .../CreateFlightCommandHandlerTests.cs | 1 - .../Identity/src/Identity.Api/Program.cs | 11 +- .../src/Identity.Api/appsettings.json | 3 +- .../src/Identity.Api/appsettings.test.json | 3 +- ...-key-DBA1A35FADC54B3029F893520A76F5EF.json | 1 + .../PersistMessageConfiguration.cs | 43 --- .../src/Identity/Data/IdentityDataSeeder.cs | 22 +- .../20220418181648_Initial.Designer.cs | 328 ---------------- ...21202152_Add-Internal-Messages.Designer.cs | 360 ------------------ .../20220421202152_Add-Internal-Messages.cs | 36 -- .../20220422121534_Update-EventId.Designer.cs | 360 ------------------ .../20220422121534_Update-EventId.cs | 25 -- ...121846_Update-Internal-EventId.Designer.cs | 360 ------------------ .../20220422121846_Update-Internal-EventId.cs | 25 -- .../20220616123336_Add-PersistMessages.cs | 82 ---- ....cs => 20220728175937_initial.Designer.cs} | 39 +- ...8_Initial.cs => 20220728175937_initial.cs} | 23 +- .../IdentityContextModelSnapshot.cs | 35 -- .../Identity/src/Identity/EventMapper.cs | 2 +- .../src/Identity/Extensions/CoreExtensions.cs | 15 + .../Identity/Extensions/MediatRExtensions.cs | 1 - .../Identity/src/Identity/Identity.csproj | 5 + .../RegisterNewUserCommandHandler.cs | 3 +- .../Identity/src/Identity/IdentityRoot.cs | 3 +- .../Fakes/FakeRegisterNewUserCommand.cs | 1 + .../Passenger/src/Passenger.Api/Program.cs | 6 +- .../src/Passenger.Api/appsettings.json | 7 +- .../src/Passenger.Api/appsettings.test.json | 3 +- .../PersistMessageConfiguration.cs | 42 -- .../20220616122705_Add-PersistMessages.cs | 38 -- ....cs => 20220728180020_initial.Designer.cs} | 2 +- ...3_initial.cs => 20220728180020_initial.cs} | 0 .../PassengerDbContextModelSnapshot.cs | 35 -- .../src/Passenger/Data/PassengerDbContext.cs | 3 +- .../Passenger/Data/PassengerReadDbContext.cs | 17 + .../Passenger/src/Passenger/EventMapper.cs | 13 +- .../Passenger/Extensions/CoreExtensions.cs | 17 + .../RegisterNewUserConsumerHandler.cs | 21 +- .../Passenger/src/Passenger/Passenger.csproj | 1 - .../Domain/PassengerCreatedDomainEvent.cs | 4 +- ...ssengerRegistrationCompletedDomainEvent.cs | 7 + .../CompleteRegisterPassengerCommand.cs | 3 +- .../CompleteRegisterPassengerMongoCommand.cs | 24 ++ ...eteRegisterPassengerMongoCommandHandler.cs | 56 +++ .../Passengers/Features/PassengerMappings.cs | 7 + .../Passenger/Passengers/Models/Passenger.cs | 19 +- .../Models/Reads/PassengerReadModel.cs | 12 + 150 files changed, 1011 insertions(+), 3365 deletions(-) create mode 100644 src/BuildingBlocks/Core/Event/IInternalCommand.cs delete mode 100644 src/BuildingBlocks/Core/Event/IInternalCommnad.cs rename src/BuildingBlocks/Core/Model/{Entity.cs => Audit.cs} (87%) rename src/BuildingBlocks/Core/Model/{IEntity.cs => IAudit.cs} (91%) delete mode 100644 src/BuildingBlocks/MessageProcessor/PersistMessageProcessor.cs rename src/{Services/Booking/src/Booking => BuildingBlocks/PersistMessageProcessor}/Data/Configurations/PersistMessageConfiguration.cs (85%) create mode 100644 src/BuildingBlocks/PersistMessageProcessor/Data/DesignTimeDbContextFactory.cs rename src/{Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.Designer.cs => BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.Designer.cs} (53%) rename src/{Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.cs => BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.cs} (77%) create mode 100644 src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/PersistMessageDbContextModelSnapshot.cs create mode 100644 src/BuildingBlocks/PersistMessageProcessor/Data/PersistMessageDbContext.cs create mode 100644 src/BuildingBlocks/PersistMessageProcessor/Data/readme.md rename src/BuildingBlocks/{MessageProcessor => PersistMessageProcessor}/Extensions.cs (50%) create mode 100644 src/BuildingBlocks/PersistMessageProcessor/IPersistMessageDbContext.cs rename src/BuildingBlocks/{MessageProcessor => PersistMessageProcessor}/IPersistMessageProcessor.cs (88%) rename src/BuildingBlocks/{MessageProcessor => PersistMessageProcessor}/MessageDeliveryType.cs (63%) rename src/BuildingBlocks/{MessageProcessor => PersistMessageProcessor}/MessageStatus.cs (56%) rename src/BuildingBlocks/{MessageProcessor => PersistMessageProcessor}/PersistMessage.cs (81%) rename src/BuildingBlocks/{MessageProcessor => PersistMessageProcessor}/PersistMessageBackgroundService.cs (66%) rename src/BuildingBlocks/{MessageProcessor => PersistMessageProcessor}/PersistMessageOptions.cs (56%) create mode 100644 src/BuildingBlocks/PersistMessageProcessor/PersistMessageProcessor.cs create mode 100644 src/BuildingBlocks/Utils/CurrentUserProvider.cs create mode 100644 src/Services/Booking/src/Booking/Booking/Models/Reads/BookingReadModel.cs delete mode 100644 src/Services/Booking/src/Booking/Data/BookingDbContext.cs create mode 100644 src/Services/Booking/src/Booking/Data/BookingReadDbContext.cs delete mode 100644 src/Services/Booking/src/Booking/Data/Configurations/BookingConfiguration.cs delete mode 100644 src/Services/Booking/src/Booking/Data/DesignTimeDbContextFactory.cs delete mode 100644 src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.Designer.cs delete mode 100644 src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.cs delete mode 100644 src/Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.Designer.cs delete mode 100644 src/Services/Booking/src/Booking/Data/Migrations/BookingDbContextModelSnapshot.cs delete mode 100644 src/Services/Booking/src/Booking/Data/readme.md create mode 100644 src/Services/Booking/src/Booking/Extensions/CoreExtensions.cs delete mode 100644 src/Services/Flight/src/Flight/Data/Configurations/PersistMessageConfiguration.cs delete mode 100644 src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.Designer.cs delete mode 100644 src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.cs rename src/Services/Flight/src/Flight/Data/Migrations/{20220511215248_Init.Designer.cs => 20220728175834_Init.Designer.cs} (99%) rename src/Services/Flight/src/Flight/Data/Migrations/{20220511215248_Init.cs => 20220728175834_Init.cs} (98%) create mode 100644 src/Services/Flight/src/Flight/Extensions/CoreExtensions.cs create mode 100644 src/Services/Identity/src/Identity.Api/keys/is-signing-key-DBA1A35FADC54B3029F893520A76F5EF.json delete mode 100644 src/Services/Identity/src/Identity/Data/Configurations/PersistMessageConfiguration.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220418181648_Initial.Designer.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.Designer.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.Designer.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.Designer.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.cs delete mode 100644 src/Services/Identity/src/Identity/Data/Migrations/20220616123336_Add-PersistMessages.cs rename src/Services/Identity/src/Identity/Data/Migrations/{20220616123336_Add-PersistMessages.Designer.cs => 20220728175937_initial.Designer.cs} (88%) rename src/Services/Identity/src/Identity/Data/Migrations/{20220418181648_Initial.cs => 20220728175937_initial.cs} (89%) create mode 100644 src/Services/Identity/src/Identity/Extensions/CoreExtensions.cs delete mode 100644 src/Services/Passenger/src/Passenger/Data/Configurations/PersistMessageConfiguration.cs delete mode 100644 src/Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.cs rename src/Services/Passenger/src/Passenger/Data/Migrations/{20220523195643_initial.Designer.cs => 20220728180020_initial.Designer.cs} (98%) rename src/Services/Passenger/src/Passenger/Data/Migrations/{20220523195643_initial.cs => 20220728180020_initial.cs} (100%) create mode 100644 src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs create mode 100644 src/Services/Passenger/src/Passenger/Extensions/CoreExtensions.cs create mode 100644 src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerRegistrationCompletedDomainEvent.cs create mode 100644 src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommand.cs create mode 100644 src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommandHandler.cs create mode 100644 src/Services/Passenger/src/Passenger/Passengers/Models/Reads/PassengerReadModel.cs diff --git a/booking.rest b/booking.rest index 5dc528d..b76f659 100644 --- a/booking.rest +++ b/booking.rest @@ -24,7 +24,7 @@ Content-Type: application/x-www-form-urlencoded grant_type=password &client_id=client &client_secret=secret -&username=meysamh +&username=samh &password=Admin@123456 &scope=flight-api ### @@ -39,11 +39,11 @@ Content-Type: application/json authorization: bearer {{Authenticate.response.body.access_token}} { - "firstName": "John6", - "lastName": "Doe6", - "username": "admin6", - "passportNumber": "1234567896", - "email": "admin6@admin.com", + "firstName": "John", + "lastName": "Do", + "username": "admin", + "passportNumber": "1290000000", + "email": "admin@admin.com", "password": "Admin6@12345", "confirmPassword": "Admin6@12345" } @@ -219,7 +219,7 @@ Content-Type: application/json authorization: bearer {{Authenticate.response.body.access_token}} { - "passportNumber": "1234567896", + "passportNumber": "123456789", "passengerType": 1, "age": 30 } @@ -251,7 +251,7 @@ Content-Type: application/json authorization: bearer {{Authenticate.response.body.access_token}} { - "passengerId": 1, + "passengerId": 4776722699124736, "flightId": 1, "description": "I want to fly to iran" } diff --git a/src/BuildingBlocks/Contracts/EventBus.Messages/PassengerContracts.cs b/src/BuildingBlocks/Contracts/EventBus.Messages/PassengerContracts.cs index 4e4b9d8..aadff7c 100644 --- a/src/BuildingBlocks/Contracts/EventBus.Messages/PassengerContracts.cs +++ b/src/BuildingBlocks/Contracts/EventBus.Messages/PassengerContracts.cs @@ -1,6 +1,6 @@ +using BuildingBlocks.Core.Event; + namespace BuildingBlocks.Contracts.EventBus.Messages; -public class PassengerContracts -{ - -} \ No newline at end of file +public record PassengerRegistrationCompleted(long Id) : IIntegrationEvent; +public record PassengerCreated(long Id) : IIntegrationEvent; diff --git a/src/BuildingBlocks/Core/Event/IEvent.cs b/src/BuildingBlocks/Core/Event/IEvent.cs index 5bb222a..9ae26c7 100644 --- a/src/BuildingBlocks/Core/Event/IEvent.cs +++ b/src/BuildingBlocks/Core/Event/IEvent.cs @@ -1,10 +1,11 @@ +using BuildingBlocks.IdsGenerator; using MediatR; namespace BuildingBlocks.Core.Event; public interface IEvent : INotification { - Guid EventId => Guid.NewGuid(); + long EventId => SnowFlakIdGenerator.NewId(); public DateTime OccurredOn => DateTime.Now; public string EventType => GetType().AssemblyQualifiedName; } diff --git a/src/BuildingBlocks/Core/Event/IInternalCommand.cs b/src/BuildingBlocks/Core/Event/IInternalCommand.cs new file mode 100644 index 0000000..a1dc9e1 --- /dev/null +++ b/src/BuildingBlocks/Core/Event/IInternalCommand.cs @@ -0,0 +1,5 @@ +namespace BuildingBlocks.Core.Event; + +public interface IInternalCommand : IEvent +{ +} diff --git a/src/BuildingBlocks/Core/Event/IInternalCommnad.cs b/src/BuildingBlocks/Core/Event/IInternalCommnad.cs deleted file mode 100644 index 185c0f7..0000000 --- a/src/BuildingBlocks/Core/Event/IInternalCommnad.cs +++ /dev/null @@ -1,11 +0,0 @@ -using BuildingBlocks.IdsGenerator; -using BuildingBlocks.Utils; - -public interface IInternalCommand -{ - public long Id => SnowFlakIdGenerator.NewId(); - - public DateTime OccurredOn => DateTime.Now; - - public string Type => TypeProvider.GetTypeName(GetType()); -} diff --git a/src/BuildingBlocks/Core/Event/InternalCommand.cs b/src/BuildingBlocks/Core/Event/InternalCommand.cs index 38eb014..68ba81a 100644 --- a/src/BuildingBlocks/Core/Event/InternalCommand.cs +++ b/src/BuildingBlocks/Core/Event/InternalCommand.cs @@ -1,14 +1,9 @@ -using BuildingBlocks.IdsGenerator; -using BuildingBlocks.Utils; -using ICommand = BuildingBlocks.Core.CQRS.ICommand; +using BuildingBlocks.Core.CQRS; +using BuildingBlocks.IdsGenerator; namespace BuildingBlocks.Core.Event; public class InternalCommand : IInternalCommand, ICommand { - public long Id { get; set; } = SnowFlakIdGenerator.NewId(); - - public DateTime OccurredOn => DateTime.Now; - - public string Type { get => TypeProvider.GetTypeName(GetType()); } + public long Id { get; init; } = SnowFlakIdGenerator.NewId(); } diff --git a/src/BuildingBlocks/Core/EventDispatcher.cs b/src/BuildingBlocks/Core/EventDispatcher.cs index 035bec4..cce8628 100644 --- a/src/BuildingBlocks/Core/EventDispatcher.cs +++ b/src/BuildingBlocks/Core/EventDispatcher.cs @@ -1,6 +1,6 @@ using System.Security.Claims; using BuildingBlocks.Core.Event; -using BuildingBlocks.MessageProcessor; +using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.Web; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; @@ -31,12 +31,16 @@ public sealed class EventDispatcher : IEventDispatcher } - public async Task SendAsync(IReadOnlyList events, EventType eventType = default, + public async Task SendAsync(IReadOnlyList events, Type type = null, CancellationToken cancellationToken = default) where T : IEvent { if (events.Count > 0) { + var eventType = type != null && type.IsAssignableTo(typeof(IInternalCommand)) + ? EventType.InternalCommand + : EventType.DomainEvent; + async Task PublishIntegrationEvent(IReadOnlyList integrationEvents) { foreach (var integrationEvent in integrationEvents) @@ -63,7 +67,7 @@ public sealed class EventDispatcher : IEventDispatcher break; } - if (eventType == EventType.InternalCommand) + if (type != null && eventType == EventType.InternalCommand) { var internalMessages = await MapDomainEventToInternalCommandAsync(events as IReadOnlyList) .ConfigureAwait(false); @@ -76,10 +80,10 @@ public sealed class EventDispatcher : IEventDispatcher } } - public async Task SendAsync(T @event, EventType eventType = default, + public async Task SendAsync(T @event, Type type = null, CancellationToken cancellationToken = default) where T : IEvent => - await SendAsync(new[] {@event}, eventType, cancellationToken); + await SendAsync(new[] {@event}, type, cancellationToken); private Task> MapDomainEventToIntegrationEventAsync( @@ -111,12 +115,12 @@ public sealed class EventDispatcher : IEventDispatcher } - private Task> MapDomainEventToInternalCommandAsync( + private Task> MapDomainEventToInternalCommandAsync( IReadOnlyList events) { _logger.LogTrace("Processing internal message start..."); - var internalCommands = new List(); + var internalCommands = new List(); using var scope = _serviceScopeFactory.CreateScope(); foreach (var @event in events) { @@ -132,7 +136,7 @@ public sealed class EventDispatcher : IEventDispatcher _logger.LogTrace("Processing internal message done..."); - return Task.FromResult>(internalCommands); + return Task.FromResult>(internalCommands); } private IEnumerable GetWrappedIntegrationEvents(IReadOnlyList domainEvents) diff --git a/src/BuildingBlocks/Core/IEventDispatcher.cs b/src/BuildingBlocks/Core/IEventDispatcher.cs index 4e7a795..d56243e 100644 --- a/src/BuildingBlocks/Core/IEventDispatcher.cs +++ b/src/BuildingBlocks/Core/IEventDispatcher.cs @@ -4,8 +4,8 @@ namespace BuildingBlocks.Core; public interface IEventDispatcher { - public Task SendAsync(IReadOnlyList events, EventType eventType = default, CancellationToken cancellationToken = default) + public Task SendAsync(IReadOnlyList events, Type type = null, CancellationToken cancellationToken = default) where T : IEvent; - public Task SendAsync(T @event, EventType eventType = default, CancellationToken cancellationToken = default) + public Task SendAsync(T @event, Type type = null, CancellationToken cancellationToken = default) where T : IEvent; } diff --git a/src/BuildingBlocks/Core/IEventMapper.cs b/src/BuildingBlocks/Core/IEventMapper.cs index 26f552c..041bc92 100644 --- a/src/BuildingBlocks/Core/IEventMapper.cs +++ b/src/BuildingBlocks/Core/IEventMapper.cs @@ -5,5 +5,5 @@ namespace BuildingBlocks.Core; public interface IEventMapper { IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event); - InternalCommand MapToInternalCommand(IDomainEvent @event); + IInternalCommand MapToInternalCommand(IDomainEvent @event); } diff --git a/src/BuildingBlocks/Core/Model/Aggregate.cs b/src/BuildingBlocks/Core/Model/Aggregate.cs index b90d19b..d68a9c5 100644 --- a/src/BuildingBlocks/Core/Model/Aggregate.cs +++ b/src/BuildingBlocks/Core/Model/Aggregate.cs @@ -2,11 +2,11 @@ namespace BuildingBlocks.Core.Model { - public abstract class Aggregate : Aggregate + public abstract record Aggregate : Aggregate { } - public abstract class Aggregate : Entity, IAggregate + public abstract record Aggregate : Audit, IAggregate { private readonly List _domainEvents = new(); public IReadOnlyList DomainEvents => _domainEvents.AsReadOnly(); diff --git a/src/BuildingBlocks/Core/Model/Entity.cs b/src/BuildingBlocks/Core/Model/Audit.cs similarity index 87% rename from src/BuildingBlocks/Core/Model/Entity.cs rename to src/BuildingBlocks/Core/Model/Audit.cs index a8eaaaa..eaf75ed 100644 --- a/src/BuildingBlocks/Core/Model/Entity.cs +++ b/src/BuildingBlocks/Core/Model/Audit.cs @@ -1,6 +1,6 @@ namespace BuildingBlocks.Core.Model; -public abstract class Entity : IEntity +public abstract record Audit : IAudit { public DateTime? CreatedAt { get; set; } public long? CreatedBy { get; set; } diff --git a/src/BuildingBlocks/Core/Model/IAggregate.cs b/src/BuildingBlocks/Core/Model/IAggregate.cs index b451bd9..f5e125f 100644 --- a/src/BuildingBlocks/Core/Model/IAggregate.cs +++ b/src/BuildingBlocks/Core/Model/IAggregate.cs @@ -2,7 +2,7 @@ namespace BuildingBlocks.Core.Model; -public interface IAggregate : IEntity +public interface IAggregate : IAudit { IReadOnlyList DomainEvents { get; } IEvent[] ClearDomainEvents(); diff --git a/src/BuildingBlocks/Core/Model/IEntity.cs b/src/BuildingBlocks/Core/Model/IAudit.cs similarity index 91% rename from src/BuildingBlocks/Core/Model/IEntity.cs rename to src/BuildingBlocks/Core/Model/IAudit.cs index fcffe38..7d463a7 100644 --- a/src/BuildingBlocks/Core/Model/IEntity.cs +++ b/src/BuildingBlocks/Core/Model/IAudit.cs @@ -1,6 +1,6 @@ namespace BuildingBlocks.Core.Model; -public interface IEntity +public interface IAudit { public DateTime? CreatedAt { get; set; } public long? CreatedBy { get; set; } diff --git a/src/BuildingBlocks/EFCore/AppDbContextBase.cs b/src/BuildingBlocks/EFCore/AppDbContextBase.cs index e404e50..9a0852a 100644 --- a/src/BuildingBlocks/EFCore/AppDbContextBase.cs +++ b/src/BuildingBlocks/EFCore/AppDbContextBase.cs @@ -1,10 +1,9 @@ using System.Collections.Immutable; using System.Data; -using System.Reflection; -using System.Security.Claims; using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Model; -using Microsoft.AspNetCore.Http; +using BuildingBlocks.Utils; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; @@ -12,13 +11,13 @@ namespace BuildingBlocks.EFCore; public abstract class AppDbContextBase : DbContext, IDbContext { - private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ICurrentUserProvider _currentUserProvider; private IDbContextTransaction _currentTransaction; - protected AppDbContextBase(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base(options) + protected AppDbContextBase(DbContextOptions options, ICurrentUserProvider currentUserProvider = null) : base(options) { - _httpContextAccessor = httpContextAccessor; + _currentUserProvider = currentUserProvider; } protected override void OnModelCreating(ModelBuilder builder) @@ -92,13 +91,10 @@ public abstract class AppDbContextBase : DbContext, IDbContext // ref: https://www.meziantou.net/entity-framework-core-soft-delete-using-query-filters.htm private void OnBeforeSaving() { - var nameIdentifier = _httpContextAccessor?.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); - - long.TryParse(nameIdentifier, out var userId); - foreach (var entry in ChangeTracker.Entries()) { var isAuditable = entry.Entity.GetType().IsAssignableTo(typeof(IAggregate)); + var userId = _currentUserProvider?.GetCurrentUserId(); if (isAuditable) { diff --git a/src/BuildingBlocks/EFCore/EfTxBehavior.cs b/src/BuildingBlocks/EFCore/EfTxBehavior.cs index 060c954..15dbc6f 100644 --- a/src/BuildingBlocks/EFCore/EfTxBehavior.cs +++ b/src/BuildingBlocks/EFCore/EfTxBehavior.cs @@ -57,17 +57,15 @@ public class EfTxBehavior : IPipelineBehavior), typeof(TRequest).FullName); - await _dbContextBase.CommitTransactionAsync(cancellationToken); - var domainEvents = _dbContextBase.GetDomainEvents(); - var eventType = typeof(TRequest).IsAssignableTo(typeof(IInternalCommand)) ? EventType.InternalCommand : EventType.DomainEvent; + await _eventDispatcher.SendAsync(domainEvents.ToArray(), typeof(TRequest), cancellationToken); - await _eventDispatcher.SendAsync(domainEvents.ToArray(), eventType, cancellationToken); + await _dbContextBase.CommitTransactionAsync(cancellationToken); return response; } - catch(System.Exception ex) + catch (System.Exception ex) { await _dbContextBase.RollbackTransactionAsync(cancellationToken); throw; diff --git a/src/BuildingBlocks/EFCore/Extensions.cs b/src/BuildingBlocks/EFCore/Extensions.cs index a4bf0cd..49aa6cd 100644 --- a/src/BuildingBlocks/EFCore/Extensions.cs +++ b/src/BuildingBlocks/EFCore/Extensions.cs @@ -1,8 +1,8 @@ using System.Linq.Expressions; using BuildingBlocks.Core.Model; +using BuildingBlocks.PersistMessageProcessor.Data; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Hosting.Infrastructure; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.Extensions.Configuration; @@ -45,7 +45,7 @@ public static class Extensions { Expression> filterExpr = e => !e.IsDeleted; foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes() - .Where(m => m.ClrType.IsAssignableTo(typeof(IEntity)))) + .Where(m => m.ClrType.IsAssignableTo(typeof(IAudit)))) { // modify expression to handle correct child type var parameter = Expression.Parameter(mutableEntityType.ClrType); @@ -63,6 +63,9 @@ public static class Extensions { using var scope = serviceProvider.CreateScope(); + var persistMessageContext = scope.ServiceProvider.GetRequiredService(); + await persistMessageContext.Database.MigrateAsync(); + var context = scope.ServiceProvider.GetRequiredService(); await context.Database.MigrateAsync(); } diff --git a/src/BuildingBlocks/EFCore/IDbContext.cs b/src/BuildingBlocks/EFCore/IDbContext.cs index 3fed9ed..186d1b2 100644 --- a/src/BuildingBlocks/EFCore/IDbContext.cs +++ b/src/BuildingBlocks/EFCore/IDbContext.cs @@ -1,6 +1,4 @@ -using System.Data; using BuildingBlocks.Core.Event; -using BuildingBlocks.MessageProcessor; using Microsoft.EntityFrameworkCore; namespace BuildingBlocks.EFCore; @@ -9,7 +7,7 @@ public interface IDbContext { DbSet Set() where TEntity : class; - DbSet PersistMessages => Set(); + IReadOnlyList GetDomainEvents(); Task BeginTransactionAsync(CancellationToken cancellationToken = default); Task CommitTransactionAsync(CancellationToken cancellationToken = default); diff --git a/src/BuildingBlocks/EventStoreDB/Config.cs b/src/BuildingBlocks/EventStoreDB/Config.cs index 2ab8901..14f8977 100644 --- a/src/BuildingBlocks/EventStoreDB/Config.cs +++ b/src/BuildingBlocks/EventStoreDB/Config.cs @@ -68,7 +68,8 @@ public static class EventStoreDBConfigExtensions ); } - public static IServiceCollection AddProjections(this IServiceCollection services, params Assembly[] assembliesToScan) + public static IServiceCollection AddProjections(this IServiceCollection services, + params Assembly[] assembliesToScan) { services.AddSingleton(); @@ -81,7 +82,7 @@ public static class EventStoreDBConfigExtensions { services.Scan(scan => scan .FromAssemblies(assembliesToScan) - .AddClasses(classes => classes.AssignableTo()) // Filter classes + .AddClasses(classes => classes.AssignableTo()) // Filter classes .AsImplementedInterfaces() .WithTransientLifetime()); } diff --git a/src/BuildingBlocks/EventStoreDB/Events/AggregateEventSourcing.cs b/src/BuildingBlocks/EventStoreDB/Events/AggregateEventSourcing.cs index 853d631..cb4d5a9 100644 --- a/src/BuildingBlocks/EventStoreDB/Events/AggregateEventSourcing.cs +++ b/src/BuildingBlocks/EventStoreDB/Events/AggregateEventSourcing.cs @@ -3,7 +3,7 @@ using BuildingBlocks.Core.Model; namespace BuildingBlocks.EventStoreDB.Events { - public abstract class AggregateEventSourcing : Entity, IAggregateEventSourcing + public abstract record AggregateEventSourcing : Audit, IAggregateEventSourcing { private readonly List _domainEvents = new(); public IReadOnlyList DomainEvents => _domainEvents.AsReadOnly(); @@ -13,9 +13,9 @@ namespace BuildingBlocks.EventStoreDB.Events _domainEvents.Add(domainEvent); } - public IEvent[] ClearDomainEvents() + public IDomainEvent[] ClearDomainEvents() { - IEvent[] dequeuedEvents = _domainEvents.ToArray(); + var dequeuedEvents = _domainEvents.ToArray(); _domainEvents.Clear(); diff --git a/src/BuildingBlocks/EventStoreDB/Events/IAggregateEventSourcing.cs b/src/BuildingBlocks/EventStoreDB/Events/IAggregateEventSourcing.cs index c13a627..d3f41b4 100644 --- a/src/BuildingBlocks/EventStoreDB/Events/IAggregateEventSourcing.cs +++ b/src/BuildingBlocks/EventStoreDB/Events/IAggregateEventSourcing.cs @@ -3,10 +3,10 @@ using BuildingBlocks.Core.Model; namespace BuildingBlocks.EventStoreDB.Events { - public interface IAggregateEventSourcing : IProjection, IEntity + public interface IAggregateEventSourcing : IProjection, IAudit { IReadOnlyList DomainEvents { get; } - IEvent[] ClearDomainEvents(); + IDomainEvent[] ClearDomainEvents(); long Version { get; } } diff --git a/src/BuildingBlocks/EventStoreDB/Repository/EventStoreDBRepository.cs b/src/BuildingBlocks/EventStoreDB/Repository/EventStoreDBRepository.cs index 6d26cc2..8dee798 100644 --- a/src/BuildingBlocks/EventStoreDB/Repository/EventStoreDBRepository.cs +++ b/src/BuildingBlocks/EventStoreDB/Repository/EventStoreDBRepository.cs @@ -8,12 +8,16 @@ public interface IEventStoreDBRepository where T : class, IAggregateEventSour { Task Find(long id, CancellationToken cancellationToken); Task Add(T aggregate, CancellationToken cancellationToken); - Task Update(T aggregate, long? expectedRevision = null, CancellationToken cancellationToken = default); + + Task Update(T aggregate, long? expectedRevision = null, + CancellationToken cancellationToken = default); + Task Delete(T aggregate, long? expectedRevision = null, CancellationToken cancellationToken = default); } -public class EventStoreDBRepository: IEventStoreDBRepository where T : class, IAggregateEventSourcing +public class EventStoreDBRepository : IEventStoreDBRepository where T : class, IAggregateEventSourcing { + private static readonly long _currentUserId; private readonly EventStoreClient eventStore; public EventStoreDBRepository(EventStoreClient eventStore) @@ -21,11 +25,13 @@ public class EventStoreDBRepository: IEventStoreDBRepository where T : cla this.eventStore = eventStore ?? throw new ArgumentNullException(nameof(eventStore)); } - public Task Find(long id, CancellationToken cancellationToken) => - eventStore.AggregateStream( + public Task Find(long id, CancellationToken cancellationToken) + { + return eventStore.AggregateStream( id, cancellationToken ); + } public async Task Add(T aggregate, CancellationToken cancellationToken = default) { @@ -38,7 +44,8 @@ public class EventStoreDBRepository: IEventStoreDBRepository where T : cla return result.NextExpectedStreamRevision; } - public async Task Update(T aggregate, long? expectedRevision = null, CancellationToken cancellationToken = default) + public async Task Update(T aggregate, long? expectedRevision = null, + CancellationToken cancellationToken = default) { var nextVersion = expectedRevision ?? aggregate.Version; @@ -51,8 +58,11 @@ public class EventStoreDBRepository: IEventStoreDBRepository where T : cla return result.NextExpectedStreamRevision; } - public Task Delete(T aggregate, long? expectedRevision = null, CancellationToken cancellationToken = default) => - Update(aggregate, expectedRevision, cancellationToken); + public Task Delete(T aggregate, long? expectedRevision = null, + CancellationToken cancellationToken = default) + { + return Update(aggregate, expectedRevision, cancellationToken); + } private static IEnumerable GetEventsToStore(T aggregate) { diff --git a/src/BuildingBlocks/EventStoreDB/Repository/RepositoryExtensions.cs b/src/BuildingBlocks/EventStoreDB/Repository/RepositoryExtensions.cs index be1c408..66c7c9e 100644 --- a/src/BuildingBlocks/EventStoreDB/Repository/RepositoryExtensions.cs +++ b/src/BuildingBlocks/EventStoreDB/Repository/RepositoryExtensions.cs @@ -28,6 +28,6 @@ public static class RepositoryExtensions action(entity); - return await repository.Update(entity, expectedVersion, cancellationToken); + return await repository.Update(entity, expectedVersion,cancellationToken); } } diff --git a/src/BuildingBlocks/MassTransit/ConsumeFilter.cs b/src/BuildingBlocks/MassTransit/ConsumeFilter.cs index 297a85d..a4f7c9b 100644 --- a/src/BuildingBlocks/MassTransit/ConsumeFilter.cs +++ b/src/BuildingBlocks/MassTransit/ConsumeFilter.cs @@ -1,5 +1,5 @@ using BuildingBlocks.Core.Event; -using BuildingBlocks.MessageProcessor; +using BuildingBlocks.PersistMessageProcessor; using MassTransit; namespace BuildingBlocks.MassTransit; diff --git a/src/BuildingBlocks/MessageProcessor/PersistMessageProcessor.cs b/src/BuildingBlocks/MessageProcessor/PersistMessageProcessor.cs deleted file mode 100644 index 677c30a..0000000 --- a/src/BuildingBlocks/MessageProcessor/PersistMessageProcessor.cs +++ /dev/null @@ -1,208 +0,0 @@ -using System.Linq.Expressions; -using System.Text.Json; -using Ardalis.GuardClauses; -using BuildingBlocks.Core.Event; -using BuildingBlocks.EFCore; -using BuildingBlocks.Utils; -using MassTransit; -using MediatR; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; - -namespace BuildingBlocks.MessageProcessor; - -public class PersistMessageProcessor : IPersistMessageProcessor -{ - private readonly ILogger _logger; - private readonly IMediator _mediator; - private readonly IDbContext _dbContext; - private readonly IPublishEndpoint _publishEndpoint; - - public PersistMessageProcessor( - ILogger logger, - IMediator mediator, - IDbContext dbContext, - IPublishEndpoint publishEndpoint) - { - _logger = logger; - _mediator = mediator; - _dbContext = dbContext; - _publishEndpoint = publishEndpoint; - } - - public async Task PublishMessageAsync( - TMessageEnvelope messageEnvelope, - CancellationToken cancellationToken = default) - where TMessageEnvelope : MessageEnvelope - { - await SavePersistMessageAsync(messageEnvelope, MessageDeliveryType.Outbox, cancellationToken); - } - - public Task AddReceivedMessageAsync(TMessageEnvelope messageEnvelope, - CancellationToken cancellationToken = default) where TMessageEnvelope : MessageEnvelope - { - return SavePersistMessageAsync(messageEnvelope, MessageDeliveryType.Inbox, cancellationToken); - } - - public async Task AddInternalMessageAsync(TCommand internalCommand, - CancellationToken cancellationToken = default) where TCommand : class, IInternalCommand - { - await SavePersistMessageAsync(new MessageEnvelope(internalCommand), MessageDeliveryType.Internal, - cancellationToken); - } - - public async Task> GetByFilterAsync(Expression> predicate, CancellationToken cancellationToken = default) - { - var b = (await _dbContext.PersistMessages.Where(predicate).ToListAsync(cancellationToken)).AsReadOnly(); - return b; - } - - public Task ExistMessageAsync(Guid messageId, CancellationToken cancellationToken = default) - { - return _dbContext.PersistMessages.FirstOrDefaultAsync(x => - x.Id == messageId && - x.DeliveryType == MessageDeliveryType.Inbox && - x.MessageStatus == MessageStatus.Processed, - cancellationToken); - } - - public async Task ProcessAsync( - Guid messageId, - MessageDeliveryType deliveryType, - CancellationToken cancellationToken = default) - { - var message = - await _dbContext.PersistMessages.FirstOrDefaultAsync( - x => x.Id == messageId && x.DeliveryType == deliveryType, cancellationToken); - - if (message is null) - return; - - switch (deliveryType) - { - case MessageDeliveryType.Internal: - await ProcessInternalAsync(message, cancellationToken); - break; - case MessageDeliveryType.Outbox: - await ProcessOutboxAsync(message, cancellationToken); - break; - } - - await ChangeMessageStatusAsync(message, cancellationToken); - } - - - public async Task ProcessAllAsync(CancellationToken cancellationToken = default) - { - var messages = await _dbContext.PersistMessages.Where(x => x.MessageStatus != MessageStatus.Processed) - .ToListAsync(cancellationToken); - - foreach (var message in messages) - { - await ProcessAsync(message.Id, message.DeliveryType, cancellationToken); - } - } - - public async Task ProcessInboxAsync(Guid messageId, CancellationToken cancellationToken = default) - { - var message = await _dbContext.PersistMessages.FirstOrDefaultAsync( - x => x.Id == messageId && - x.DeliveryType == MessageDeliveryType.Inbox && - x.MessageStatus == MessageStatus.InProgress, - cancellationToken); - - await ChangeMessageStatusAsync(message, cancellationToken); - } - - private async Task SavePersistMessageAsync( - MessageEnvelope messageEnvelope, - MessageDeliveryType deliveryType, - CancellationToken cancellationToken = default) - { - Guard.Against.Null(messageEnvelope.Message, nameof(messageEnvelope.Message)); - - Guid id; - if (messageEnvelope.Message is IEvent message) - { - id = message.EventId; - } - else - { - id = Guid.NewGuid(); - } - - await _dbContext.PersistMessages.AddAsync( - new PersistMessage( - id, - TypeProvider.GetTypeName(messageEnvelope.Message.GetType()), - JsonSerializer.Serialize(messageEnvelope), - deliveryType), - cancellationToken); - - await _dbContext.SaveChangesAsync(cancellationToken); - - _logger.LogInformation( - "Message with id: {MessageID} and delivery type: {DeliveryType} saved in persistence message store.", - id, - deliveryType.ToString()); - - return id; - } - - private async Task ProcessOutboxAsync(PersistMessage message, CancellationToken cancellationToken) - { - MessageEnvelope? messageEnvelope = JsonSerializer.Deserialize(message.Data); - - if (messageEnvelope is null || messageEnvelope.Message is null) - return; - - var data = JsonSerializer.Deserialize(messageEnvelope.Message.ToString()!, - TypeProvider.GetType(message.DataType)); - - if (data is IEvent) - { - await _publishEndpoint.Publish((object)data, context => - { - foreach (var header in messageEnvelope.Headers) - { - context.Headers.Set(header.Key, header.Value); - } - }, cancellationToken); - - _logger.LogInformation( - "Message with id: {MessageId} and delivery type: {DeliveryType} processed from the persistence message store.", - message.Id, - message.DeliveryType); - } - } - - private async Task ProcessInternalAsync(PersistMessage message, CancellationToken cancellationToken) - { - MessageEnvelope? messageEnvelope = JsonSerializer.Deserialize(message.Data); - - if (messageEnvelope is null || messageEnvelope.Message is null) - return; - - var data = JsonSerializer.Deserialize(messageEnvelope.Message.ToString()!, - TypeProvider.GetType(message.DataType)); - - if (data is IInternalCommand internalCommand) - { - await _mediator.Send(internalCommand, cancellationToken); - - _logger.LogInformation( - "InternalCommand with id: {EventID} and delivery type: {DeliveryType} processed from the persistence message store.", - message.Id, - message.DeliveryType); - } - } - - private async Task ChangeMessageStatusAsync(PersistMessage message, CancellationToken cancellationToken) - { - message.ChangeState(MessageStatus.Processed); - - _dbContext.PersistMessages.Update(message); - - await _dbContext.SaveChangesAsync(cancellationToken); - } -} diff --git a/src/Services/Booking/src/Booking/Data/Configurations/PersistMessageConfiguration.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/Configurations/PersistMessageConfiguration.cs similarity index 85% rename from src/Services/Booking/src/Booking/Data/Configurations/PersistMessageConfiguration.cs rename to src/BuildingBlocks/PersistMessageProcessor/Data/Configurations/PersistMessageConfiguration.cs index 26c0387..60d2566 100644 --- a/src/Services/Booking/src/Booking/Data/Configurations/PersistMessageConfiguration.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/Configurations/PersistMessageConfiguration.cs @@ -1,14 +1,13 @@ -using BuildingBlocks.MessageProcessor; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; -namespace Booking.Data.Configurations; +namespace BuildingBlocks.PersistMessageProcessor.Data.Configurations; public class PersistMessageConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { - builder.ToTable("PersistMessages", BookingDbContext.DefaultSchema); + builder.ToTable("PersistMessage", PersistMessageDbContext.DefaultSchema); builder.HasKey(x => x.Id); diff --git a/src/BuildingBlocks/PersistMessageProcessor/Data/DesignTimeDbContextFactory.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/DesignTimeDbContextFactory.cs new file mode 100644 index 0000000..538c51f --- /dev/null +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/DesignTimeDbContextFactory.cs @@ -0,0 +1,16 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; + +namespace BuildingBlocks.PersistMessageProcessor.Data; + +public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory +{ + public PersistMessageDbContext CreateDbContext(string[] args) + { + var builder = new DbContextOptionsBuilder(); + + builder.UseSqlServer( + "Data Source=.\\sqlexpress;Initial Catalog=PersistMessageDB;Persist Security Info=False;Integrated Security=SSPI"); + return new PersistMessageDbContext(builder.Options); + } +} diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.Designer.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.Designer.cs similarity index 53% rename from src/Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.Designer.cs rename to src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.Designer.cs index eedd065..fbe223d 100644 --- a/src/Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.Designer.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.Designer.cs @@ -1,19 +1,20 @@ // using System; +using Booking.Data; +using BuildingBlocks.PersistMessageProcessor.Data; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Passenger.Data; #nullable disable -namespace Passenger.Data.Migrations +namespace Booking.Data.Migrations { - [DbContext(typeof(PassengerDbContext))] - [Migration("20220616122705_Add-PersistMessages")] - partial class AddPersistMessages + [DbContext(typeof(PersistMessageDbContext))] + [Migration("20220728155556_initial")] + partial class initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -24,12 +25,16 @@ namespace Passenger.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => + modelBuilder.Entity("BuildingBlocks.PersistMessageProcessor.PersistMessage", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("uniqueidentifier"); + b.Property("ApplicationName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + b.Property("Created") .HasColumnType("datetime2"); @@ -56,47 +61,7 @@ namespace Passenger.Data.Migrations b.HasKey("Id"); - b.ToTable("PersistMessages", "dbo"); - }); - - modelBuilder.Entity("Passenger.Passengers.Models.Passenger", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("Age") - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("PassengerType") - .HasColumnType("int"); - - b.Property("PassportNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("Passenger", "dbo"); + b.ToTable("PersistMessage", "dbo"); }); #pragma warning restore 612, 618 } diff --git a/src/Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.cs similarity index 77% rename from src/Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.cs rename to src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.cs index 984a0e7..b2ddd42 100644 --- a/src/Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/20220728155556_initial.cs @@ -5,16 +5,19 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace Booking.Data.Migrations { - public partial class AddPersistMessages : Migration + public partial class initial : Migration { protected override void Up(MigrationBuilder migrationBuilder) { + migrationBuilder.EnsureSchema( + name: "dbo"); + migrationBuilder.CreateTable( - name: "PersistMessages", + name: "PersistMessage", schema: "dbo", columns: table => new { - Id = table.Column(type: "uniqueidentifier", nullable: false), + Id = table.Column(type: "bigint", nullable: false), DataType = table.Column(type: "nvarchar(max)", nullable: true), Data = table.Column(type: "nvarchar(max)", nullable: true), Created = table.Column(type: "datetime2", nullable: false), @@ -24,14 +27,14 @@ namespace Booking.Data.Migrations }, constraints: table => { - table.PrimaryKey("PK_PersistMessages", x => x.Id); + table.PrimaryKey("PK_PersistMessage", x => x.Id); }); } protected override void Down(MigrationBuilder migrationBuilder) { migrationBuilder.DropTable( - name: "PersistMessages", + name: "PersistMessage", schema: "dbo"); } } diff --git a/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/PersistMessageDbContextModelSnapshot.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/PersistMessageDbContextModelSnapshot.cs new file mode 100644 index 0000000..5c56774 --- /dev/null +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/Migrations/PersistMessageDbContextModelSnapshot.cs @@ -0,0 +1,63 @@ +// +using System; +using Booking.Data; +using BuildingBlocks.PersistMessageProcessor.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Booking.Data.Migrations +{ + [DbContext(typeof(PersistMessageDbContext))] + partial class PersistMessageDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("BuildingBlocks.PersistMessageProcessor.PersistMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("Created") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("DataType") + .HasColumnType("nvarchar(max)"); + + b.Property("DeliveryType") + .IsRequired() + .HasMaxLength(50) + .IsUnicode(false) + .HasColumnType("varchar(50)"); + + b.Property("MessageStatus") + .IsRequired() + .HasMaxLength(50) + .IsUnicode(false) + .HasColumnType("varchar(50)"); + + b.Property("RetryCount") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("PersistMessage", "dbo"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/BuildingBlocks/PersistMessageProcessor/Data/PersistMessageDbContext.cs b/src/BuildingBlocks/PersistMessageProcessor/Data/PersistMessageDbContext.cs new file mode 100644 index 0000000..8aa3528 --- /dev/null +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/PersistMessageDbContext.cs @@ -0,0 +1,23 @@ +using BuildingBlocks.EFCore; +using BuildingBlocks.PersistMessageProcessor.Data.Configurations; +using BuildingBlocks.Utils; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; + +namespace BuildingBlocks.PersistMessageProcessor.Data; + +public class PersistMessageDbContext : AppDbContextBase, IPersistMessageDbContext +{ + public const string DefaultSchema = "dbo"; + + public PersistMessageDbContext(DbContextOptions options) + : base(options) + { + } + + protected override void OnModelCreating(ModelBuilder builder) + { + builder.ApplyConfiguration(new PersistMessageConfiguration()); + base.OnModelCreating(builder); + } +} diff --git a/src/BuildingBlocks/PersistMessageProcessor/Data/readme.md b/src/BuildingBlocks/PersistMessageProcessor/Data/readme.md new file mode 100644 index 0000000..b7f4097 --- /dev/null +++ b/src/BuildingBlocks/PersistMessageProcessor/Data/readme.md @@ -0,0 +1,2 @@ +dotnet ef migrations add initial --context PersistMessageDbContext -o "Data\Migrations" +dotnet ef database update --context PersistMessageDbContext diff --git a/src/BuildingBlocks/MessageProcessor/Extensions.cs b/src/BuildingBlocks/PersistMessageProcessor/Extensions.cs similarity index 50% rename from src/BuildingBlocks/MessageProcessor/Extensions.cs rename to src/BuildingBlocks/PersistMessageProcessor/Extensions.cs index f2c8fab..2a6b0f5 100644 --- a/src/BuildingBlocks/MessageProcessor/Extensions.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/Extensions.cs @@ -1,9 +1,11 @@ using BuildingBlocks.Core; -using BuildingBlocks.Mongo; +using BuildingBlocks.PersistMessageProcessor.Data; +using BuildingBlocks.Web; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -namespace BuildingBlocks.MessageProcessor; +namespace BuildingBlocks.PersistMessageProcessor; public static class Extensions { @@ -13,8 +15,15 @@ public static class Extensions .Bind(configuration.GetSection(nameof(PersistMessageOptions))) .ValidateDataAnnotations(); + var persistMessageOptions = services.GetOptions("PersistMessageOptions"); + + services.AddDbContext(options => + options.UseSqlServer(persistMessageOptions.ConnectionString, + x => x.MigrationsAssembly(typeof(PersistMessageDbContext).Assembly.GetName().Name))); + + services.AddScoped(provider => provider.GetService()); + services.AddScoped(); - services.AddScoped(); services.AddHostedService(); return services; diff --git a/src/BuildingBlocks/PersistMessageProcessor/IPersistMessageDbContext.cs b/src/BuildingBlocks/PersistMessageProcessor/IPersistMessageDbContext.cs new file mode 100644 index 0000000..2552126 --- /dev/null +++ b/src/BuildingBlocks/PersistMessageProcessor/IPersistMessageDbContext.cs @@ -0,0 +1,9 @@ +using BuildingBlocks.EFCore; +using Microsoft.EntityFrameworkCore; + +namespace BuildingBlocks.PersistMessageProcessor; + +public interface IPersistMessageDbContext : IDbContext +{ + DbSet PersistMessages => Set(); +} diff --git a/src/BuildingBlocks/MessageProcessor/IPersistMessageProcessor.cs b/src/BuildingBlocks/PersistMessageProcessor/IPersistMessageProcessor.cs similarity index 88% rename from src/BuildingBlocks/MessageProcessor/IPersistMessageProcessor.cs rename to src/BuildingBlocks/PersistMessageProcessor/IPersistMessageProcessor.cs index 150ea47..c1da1af 100644 --- a/src/BuildingBlocks/MessageProcessor/IPersistMessageProcessor.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/IPersistMessageProcessor.cs @@ -1,7 +1,7 @@ using System.Linq.Expressions; using BuildingBlocks.Core.Event; -namespace BuildingBlocks.MessageProcessor; +namespace BuildingBlocks.PersistMessageProcessor; // Ref: http://www.kamilgrzybek.com/design/the-outbox-pattern/ // Ref: https://event-driven.io/en/outbox_inbox_patterns_and_delivery_guarantees_explained/ @@ -15,7 +15,7 @@ public interface IPersistMessageProcessor CancellationToken cancellationToken = default) where TMessageEnvelope : MessageEnvelope; - Task AddReceivedMessageAsync( + Task AddReceivedMessageAsync( TMessageEnvelope messageEnvelope, CancellationToken cancellationToken = default) where TMessageEnvelope : MessageEnvelope; @@ -30,14 +30,14 @@ public interface IPersistMessageProcessor CancellationToken cancellationToken = default); Task ExistMessageAsync( - Guid messageId, + long messageId, CancellationToken cancellationToken = default); Task ProcessInboxAsync( - Guid messageId, + long messageId, CancellationToken cancellationToken = default); - Task ProcessAsync(Guid messageId, MessageDeliveryType deliveryType, CancellationToken cancellationToken = default); + Task ProcessAsync(long messageId, MessageDeliveryType deliveryType, CancellationToken cancellationToken = default); Task ProcessAllAsync(CancellationToken cancellationToken = default); } diff --git a/src/BuildingBlocks/MessageProcessor/MessageDeliveryType.cs b/src/BuildingBlocks/PersistMessageProcessor/MessageDeliveryType.cs similarity index 63% rename from src/BuildingBlocks/MessageProcessor/MessageDeliveryType.cs rename to src/BuildingBlocks/PersistMessageProcessor/MessageDeliveryType.cs index e9eff7f..9fb5dc2 100644 --- a/src/BuildingBlocks/MessageProcessor/MessageDeliveryType.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/MessageDeliveryType.cs @@ -1,4 +1,4 @@ -namespace BuildingBlocks.MessageProcessor; +namespace BuildingBlocks.PersistMessageProcessor; [Flags] public enum MessageDeliveryType diff --git a/src/BuildingBlocks/MessageProcessor/MessageStatus.cs b/src/BuildingBlocks/PersistMessageProcessor/MessageStatus.cs similarity index 56% rename from src/BuildingBlocks/MessageProcessor/MessageStatus.cs rename to src/BuildingBlocks/PersistMessageProcessor/MessageStatus.cs index c7f0cb8..028053f 100644 --- a/src/BuildingBlocks/MessageProcessor/MessageStatus.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/MessageStatus.cs @@ -1,4 +1,4 @@ -namespace BuildingBlocks.MessageProcessor; +namespace BuildingBlocks.PersistMessageProcessor; public enum MessageStatus { diff --git a/src/BuildingBlocks/MessageProcessor/PersistMessage.cs b/src/BuildingBlocks/PersistMessageProcessor/PersistMessage.cs similarity index 81% rename from src/BuildingBlocks/MessageProcessor/PersistMessage.cs rename to src/BuildingBlocks/PersistMessageProcessor/PersistMessage.cs index c884f09..4335eb2 100644 --- a/src/BuildingBlocks/MessageProcessor/PersistMessage.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/PersistMessage.cs @@ -1,8 +1,10 @@ -namespace BuildingBlocks.MessageProcessor; +using System.Reflection; + +namespace BuildingBlocks.PersistMessageProcessor; public class PersistMessage { - public PersistMessage(Guid id, string dataType, string data, MessageDeliveryType deliveryType) + public PersistMessage(long id, string dataType, string data, MessageDeliveryType deliveryType) { Id = id; DataType = dataType; @@ -13,7 +15,7 @@ public class PersistMessage RetryCount = 0; } - public Guid Id { get; private set; } + public long Id { get; private set; } public string DataType { get; private set; } public string Data { get; private set; } public DateTime Created { get; private set; } diff --git a/src/BuildingBlocks/MessageProcessor/PersistMessageBackgroundService.cs b/src/BuildingBlocks/PersistMessageProcessor/PersistMessageBackgroundService.cs similarity index 66% rename from src/BuildingBlocks/MessageProcessor/PersistMessageBackgroundService.cs rename to src/BuildingBlocks/PersistMessageProcessor/PersistMessageBackgroundService.cs index 76f50b0..09527f9 100644 --- a/src/BuildingBlocks/MessageProcessor/PersistMessageBackgroundService.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/PersistMessageBackgroundService.cs @@ -3,7 +3,7 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -namespace BuildingBlocks.MessageProcessor; +namespace BuildingBlocks.PersistMessageProcessor; public class PersistMessageBackgroundService : BackgroundService { @@ -43,17 +43,25 @@ public class PersistMessageBackgroundService : BackgroundService { while (!stoppingToken.IsCancellationRequested) { - await using (var scope = _serviceProvider.CreateAsyncScope()) + try { - var service = scope.ServiceProvider.GetRequiredService(); - await service.ProcessAllAsync(stoppingToken); + await using (var scope = _serviceProvider.CreateAsyncScope()) + { + var service = scope.ServiceProvider.GetRequiredService(); + await service.ProcessAllAsync(stoppingToken); + } + + var delay = _options.Interval is { } + ? TimeSpan.FromSeconds((int)_options.Interval) + : TimeSpan.FromSeconds(30); + + await Task.Delay(delay, stoppingToken); + } + catch (System.Exception e) + { + Console.WriteLine(e); + throw; } - - var delay = _options.Interval is { } - ? TimeSpan.FromSeconds((int)_options.Interval) - : TimeSpan.FromSeconds(30); - - await Task.Delay(delay, stoppingToken); } } } diff --git a/src/BuildingBlocks/MessageProcessor/PersistMessageOptions.cs b/src/BuildingBlocks/PersistMessageProcessor/PersistMessageOptions.cs similarity index 56% rename from src/BuildingBlocks/MessageProcessor/PersistMessageOptions.cs rename to src/BuildingBlocks/PersistMessageProcessor/PersistMessageOptions.cs index d2baa1c..2e16591 100644 --- a/src/BuildingBlocks/MessageProcessor/PersistMessageOptions.cs +++ b/src/BuildingBlocks/PersistMessageProcessor/PersistMessageOptions.cs @@ -1,7 +1,8 @@ -namespace BuildingBlocks.MessageProcessor; +namespace BuildingBlocks.PersistMessageProcessor; public class PersistMessageOptions { public int? Interval { get; set; } = 30; public bool Enabled { get; set; } = true; + public string ConnectionString { get; set; } } diff --git a/src/BuildingBlocks/PersistMessageProcessor/PersistMessageProcessor.cs b/src/BuildingBlocks/PersistMessageProcessor/PersistMessageProcessor.cs new file mode 100644 index 0000000..f1815a6 --- /dev/null +++ b/src/BuildingBlocks/PersistMessageProcessor/PersistMessageProcessor.cs @@ -0,0 +1,219 @@ +using System.Linq.Expressions; +using System.Text.Json; +using Ardalis.GuardClauses; +using BuildingBlocks.Core.Event; +using BuildingBlocks.IdsGenerator; +using BuildingBlocks.Utils; +using MassTransit; +using MediatR; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; + +namespace BuildingBlocks.PersistMessageProcessor; + +public class PersistMessageProcessor : IPersistMessageProcessor +{ + private readonly ILogger _logger; + private readonly IMediator _mediator; + private readonly IPersistMessageDbContext _persistMessageDbContext; + private readonly IPublishEndpoint _publishEndpoint; + + public PersistMessageProcessor( + ILogger logger, + IMediator mediator, + IPersistMessageDbContext persistMessageDbContext, + IPublishEndpoint publishEndpoint) + { + _logger = logger; + _mediator = mediator; + _persistMessageDbContext = persistMessageDbContext; + _publishEndpoint = publishEndpoint; + } + + public async Task PublishMessageAsync( + TMessageEnvelope messageEnvelope, + CancellationToken cancellationToken = default) + where TMessageEnvelope : MessageEnvelope + { + await SavePersistMessageAsync(messageEnvelope, MessageDeliveryType.Outbox, cancellationToken); + } + + public Task AddReceivedMessageAsync(TMessageEnvelope messageEnvelope, + CancellationToken cancellationToken = default) where TMessageEnvelope : MessageEnvelope + { + return SavePersistMessageAsync(messageEnvelope, MessageDeliveryType.Inbox, cancellationToken); + } + + public async Task AddInternalMessageAsync(TCommand internalCommand, + CancellationToken cancellationToken = default) where TCommand : class, IInternalCommand + { + await SavePersistMessageAsync(new MessageEnvelope(internalCommand), MessageDeliveryType.Internal, + cancellationToken); + } + + public async Task> GetByFilterAsync(Expression> predicate, + CancellationToken cancellationToken = default) + { + return (await _persistMessageDbContext.PersistMessages.Where(predicate).ToListAsync(cancellationToken)) + .AsReadOnly(); + } + + public Task ExistMessageAsync(long messageId, CancellationToken cancellationToken = default) + { + return _persistMessageDbContext.PersistMessages.FirstOrDefaultAsync(x => + x.Id == messageId && + x.DeliveryType == MessageDeliveryType.Inbox && + x.MessageStatus == MessageStatus.Processed, + cancellationToken); + } + + public async Task ProcessAsync( + long messageId, + MessageDeliveryType deliveryType, + CancellationToken cancellationToken = default) + { + var message = + await _persistMessageDbContext.PersistMessages.FirstOrDefaultAsync( + x => x.Id == messageId && x.DeliveryType == deliveryType, cancellationToken); + + if (message is null) + return; + + switch (deliveryType) + { + case MessageDeliveryType.Internal: + var sentInternalMessage = await ProcessInternalAsync(message, cancellationToken); + if (sentInternalMessage) + { + await ChangeMessageStatusAsync(message, cancellationToken); + break; + } + else + { + return; + } + + case MessageDeliveryType.Outbox: + var sentOutbox = await ProcessOutboxAsync(message, cancellationToken); + if (sentOutbox) + { + await ChangeMessageStatusAsync(message, cancellationToken); + break; + } + else + { + return; + } + } + } + + + public async Task ProcessAllAsync(CancellationToken cancellationToken = default) + { + var messages = await _persistMessageDbContext.PersistMessages + .Where(x => x.MessageStatus != MessageStatus.Processed) + .ToListAsync(cancellationToken); + + foreach (var message in messages) await ProcessAsync(message.Id, message.DeliveryType, cancellationToken); + } + + public async Task ProcessInboxAsync(long messageId, CancellationToken cancellationToken = default) + { + var message = await _persistMessageDbContext.PersistMessages.FirstOrDefaultAsync( + x => x.Id == messageId && + x.DeliveryType == MessageDeliveryType.Inbox && + x.MessageStatus == MessageStatus.InProgress, + cancellationToken); + + await ChangeMessageStatusAsync(message, cancellationToken); + } + + private async Task ProcessOutboxAsync(PersistMessage message, CancellationToken cancellationToken) + { + var messageEnvelope = JsonSerializer.Deserialize(message.Data); + + if (messageEnvelope is null || messageEnvelope.Message is null) + return false; + + var data = JsonSerializer.Deserialize(messageEnvelope.Message.ToString() ?? string.Empty, + TypeProvider.GetFirstMatchingTypeFromCurrentDomainAssembly(message.DataType) ?? typeof(object)); + + if (data is not IEvent) + return false; + + await _publishEndpoint.Publish(data, context => + { + foreach (var header in messageEnvelope.Headers) context.Headers.Set(header.Key, header.Value); + }, cancellationToken); + + _logger.LogInformation( + "Message with id: {MessageId} and delivery type: {DeliveryType} processed from the persistence message store.", + message.Id, + message.DeliveryType); + + return true; + } + + private async Task ProcessInternalAsync(PersistMessage message, CancellationToken cancellationToken) + { + var messageEnvelope = JsonSerializer.Deserialize(message.Data); + + if (messageEnvelope is null || messageEnvelope.Message is null) + return false; + + var data = JsonSerializer.Deserialize(messageEnvelope.Message.ToString() ?? string.Empty, + TypeProvider.GetFirstMatchingTypeFromCurrentDomainAssembly(message.DataType) ?? typeof(object)); + + if (data is not IInternalCommand internalCommand) + return false; + + await _mediator.Send(internalCommand, cancellationToken); + + _logger.LogInformation( + "InternalCommand with id: {EventID} and delivery type: {DeliveryType} processed from the persistence message store.", + message.Id, + message.DeliveryType); + + return true; + } + + private async Task SavePersistMessageAsync( + MessageEnvelope messageEnvelope, + MessageDeliveryType deliveryType, + CancellationToken cancellationToken = default) + { + Guard.Against.Null(messageEnvelope.Message, nameof(messageEnvelope.Message)); + + long id; + if (messageEnvelope.Message is IEvent message) + id = message.EventId; + else + id = SnowFlakIdGenerator.NewId(); + + await _persistMessageDbContext.PersistMessages.AddAsync( + new PersistMessage( + id, + messageEnvelope.Message.GetType().ToString(), + JsonSerializer.Serialize(messageEnvelope), + deliveryType), + cancellationToken); + + await _persistMessageDbContext.SaveChangesAsync(cancellationToken); + + _logger.LogInformation( + "Message with id: {MessageID} and delivery type: {DeliveryType} saved in persistence message store.", + id, + deliveryType.ToString()); + + return id; + } + + private async Task ChangeMessageStatusAsync(PersistMessage message, CancellationToken cancellationToken) + { + message.ChangeState(MessageStatus.Processed); + + _persistMessageDbContext.PersistMessages.Update(message); + + await _persistMessageDbContext.SaveChangesAsync(cancellationToken); + } +} diff --git a/src/BuildingBlocks/TestBase/IntegrationTestBase.cs b/src/BuildingBlocks/TestBase/IntegrationTestBase.cs index c149797..8ab33ce 100644 --- a/src/BuildingBlocks/TestBase/IntegrationTestBase.cs +++ b/src/BuildingBlocks/TestBase/IntegrationTestBase.cs @@ -1,10 +1,11 @@ using Ardalis.GuardClauses; +using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Model; using BuildingBlocks.EFCore; +using BuildingBlocks.EventStoreDB.Projections; using BuildingBlocks.MassTransit; -using BuildingBlocks.MessageProcessor; using BuildingBlocks.Mongo; -using BuildingBlocks.Utils; +using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.Web; using Grpc.Net.Client; using MassTransit; @@ -50,6 +51,7 @@ public class IntegrationTestFixture : IAsyncLifetime { TestRegistrationServices?.Invoke(services); services.ReplaceSingleton(AddHttpContextAccessorMock); + services.Unregister(); services.AddMassTransitTestHarness(x => { x.UsingRabbitMq((context, cfg) => @@ -88,9 +90,11 @@ public class IntegrationTestFixture : IAsyncLifetime public ILogger CreateLogger(ITestOutputHelper output) { if (output != null) + { return new LoggerConfiguration() .WriteTo.TestOutput(output) .CreateLogger(); + } return null; } @@ -160,7 +164,7 @@ public class IntegrationTestFixture : IAsyncLifetime var filter = await persistMessageProcessor.GetByFilterAsync(x => x.DeliveryType == MessageDeliveryType.Internal && - TypeProvider.GetTypeName(typeof(TInternalCommand)) == x.DataType); + typeof(TInternalCommand).ToString() == x.DataType); var res = filter.Any(x => x.MessageStatus == MessageStatus.Processed); @@ -294,7 +298,7 @@ public class IntegrationTestFixture : IntegrationTestFix } public Task FindAsync(long id) - where T : class, IEntity + where T : class, IAudit { return ExecuteDbContextAsync(db => db.Set().FindAsync(id).AsTask()); } @@ -319,7 +323,8 @@ public class IntegrationTestFixture : Integra public class IntegrationTestFixtureCore : IAsyncLifetime where TEntryPoint : class { - private Checkpoint _checkpoint; + private Checkpoint _checkpointDefaultDB; + private Checkpoint _checkpointPersistMessageDB; private MongoDbRunner _mongoRunner; public IntegrationTestFixtureCore(IntegrationTestFixture integrationTestFixture) @@ -332,7 +337,8 @@ public class IntegrationTestFixtureCore : IAsyncLifetime public async Task InitializeAsync() { - _checkpoint = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; + _checkpointDefaultDB = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; + _checkpointPersistMessageDB = new Checkpoint {TablesToIgnore = new[] {"__EFMigrationsHistory"}}; _mongoRunner = MongoDbRunner.Start(); var mongoOptions = Fixture.ServiceProvider.GetRequiredService>(); @@ -344,7 +350,8 @@ public class IntegrationTestFixtureCore : IAsyncLifetime public async Task DisposeAsync() { - await _checkpoint.Reset(Fixture.Configuration?.GetConnectionString("DefaultConnection")); + await _checkpointDefaultDB.Reset(Fixture.Configuration?.GetConnectionString("DefaultConnection")); + await _checkpointPersistMessageDB.Reset(Fixture.ServiceProvider.GetRequiredService>()?.Value?.ConnectionString); _mongoRunner.Dispose(); } diff --git a/src/BuildingBlocks/Utils/CurrentUserProvider.cs b/src/BuildingBlocks/Utils/CurrentUserProvider.cs new file mode 100644 index 0000000..385d393 --- /dev/null +++ b/src/BuildingBlocks/Utils/CurrentUserProvider.cs @@ -0,0 +1,29 @@ +using System.Security.Claims; +using Microsoft.AspNetCore.Http; + +namespace BuildingBlocks.Utils; + +public interface ICurrentUserProvider +{ + long? GetCurrentUserId(); +} + +public class CurrentUserProvider : ICurrentUserProvider +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + public CurrentUserProvider(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + + public long? GetCurrentUserId() + { + var nameIdentifier = _httpContextAccessor?.HttpContext?.User?.FindFirstValue(ClaimTypes.NameIdentifier); + + long.TryParse(nameIdentifier, out var userId); + + return userId; + } +} diff --git a/src/BuildingBlocks/Utils/TypeProvider.cs b/src/BuildingBlocks/Utils/TypeProvider.cs index 78adeab..826e490 100644 --- a/src/BuildingBlocks/Utils/TypeProvider.cs +++ b/src/BuildingBlocks/Utils/TypeProvider.cs @@ -1,14 +1,10 @@ -using System.Collections.Concurrent; using System.Reflection; using System.Runtime.CompilerServices; -using Ardalis.GuardClauses; namespace BuildingBlocks.Utils; public static class TypeProvider { - private static readonly ConcurrentDictionary TypeNameMap = new(); - private static readonly ConcurrentDictionary TypeMap = new(); private static bool IsRecord(this Type objectType) { return objectType.GetMethod("$") != null || @@ -34,76 +30,10 @@ public static class TypeProvider public static Type? GetFirstMatchingTypeFromCurrentDomainAssembly(string typeName) { - return AppDomain.CurrentDomain.GetAssemblies() + var result = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes().Where(x => x.FullName == typeName || x.Name == typeName)) .FirstOrDefault(); + + return result; } - - /// - /// Gets the type name from a generic Type class. - /// - /// - /// GetTypeName - public static string GetTypeName() => ToName(typeof(T)); - - /// - /// Gets the type name from a Type class. - /// - /// - /// TypeName - public static string GetTypeName(Type type) => ToName(type); - - /// - /// Gets the type name from a instance object. - /// - /// - /// TypeName - public static string GetTypeNameByObject(object o) => ToName(o.GetType()); - - /// - /// Gets the type class from a type name. - /// - /// - /// Type - public static Type GetType(string typeName) => ToType(typeName); - - public static void AddType(string name) => AddType(typeof(T), name); - - private static void AddType(Type type, string name) - { - ToName(type); - ToType(name); - } - - public static bool IsTypeRegistered() => TypeNameMap.ContainsKey(typeof(T)); - - private static string ToName(Type type) - { - Guard.Against.Null(type, nameof(type)); - - return TypeNameMap.GetOrAdd(type, _ => - { - var eventTypeName = type.FullName!.Replace(".", "_", StringComparison.Ordinal); - - TypeMap.GetOrAdd(eventTypeName, type); - - return eventTypeName; - }); - } - - private static Type ToType(string typeName) => TypeMap.GetOrAdd(typeName, _ => - { - Guard.Against.NullOrEmpty(typeName, nameof(typeName)); - - return TypeMap.GetOrAdd(typeName, _ => - { - var type = GetFirstMatchingTypeFromCurrentDomainAssembly( - typeName.Replace("_", ".", StringComparison.Ordinal))!; - - if (type == null) - throw new System.Exception($"Type map for '{typeName}' wasn't found!"); - - return type; - }); - }); } diff --git a/src/Services/Booking/src/Booking.Api/Program.cs b/src/Services/Booking/src/Booking.Api/Program.cs index c5156df..d3321e5 100644 --- a/src/Services/Booking/src/Booking.Api/Program.cs +++ b/src/Services/Booking/src/Booking.Api/Program.cs @@ -5,14 +5,17 @@ using Booking.Extensions; using BuildingBlocks.Core; using BuildingBlocks.EFCore; using BuildingBlocks.EventStoreDB; +using BuildingBlocks.EventStoreDB.Projections; using BuildingBlocks.HealthCheck; using BuildingBlocks.IdsGenerator; using BuildingBlocks.Jwt; using BuildingBlocks.Logging; using BuildingBlocks.Mapster; using BuildingBlocks.MassTransit; -using BuildingBlocks.MessageProcessor; +using BuildingBlocks.Mongo; using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.PersistMessageProcessor; +using BuildingBlocks.PersistMessageProcessor.Data; using BuildingBlocks.Swagger; using BuildingBlocks.Web; using Figgle; @@ -31,10 +34,11 @@ builder.Services.Configure(options => configuration.GetSection("Grp Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name)); -builder.Services.AddCustomDbContext(configuration); builder.Services.AddPersistMessage(configuration); +builder.Services.AddMongoDbContext(configuration); builder.AddCustomSerilog(); +builder.Services.AddCore(); builder.Services.AddJwt(); builder.Services.AddControllers(); builder.Services.AddHttpContextAccessor(); @@ -44,9 +48,6 @@ builder.Services.AddCustomMediatR(); builder.Services.AddValidatorsFromAssembly(typeof(BookingRoot).Assembly); builder.Services.AddCustomProblemDetails(); builder.Services.AddCustomMapster(typeof(BookingRoot).Assembly); -builder.Services.AddHttpContextAccessor(); - -builder.Services.AddTransient(); builder.Services.AddCustomHealthCheck(); builder.Services.AddCustomMassTransit(typeof(BookingRoot).Assembly, env); builder.Services.AddCustomOpenTelemetry(); @@ -69,7 +70,6 @@ if (app.Environment.IsDevelopment()) } app.UseSerilogRequestLogging(); -app.UseMigration(env); app.UseCorrelationId(); app.UseRouting(); app.UseHttpMetrics(); diff --git a/src/Services/Booking/src/Booking.Api/appsettings.json b/src/Services/Booking/src/Booking.Api/appsettings.json index e7fd2f7..f5fb364 100644 --- a/src/Services/Booking/src/Booking.Api/appsettings.json +++ b/src/Services/Booking/src/Booking.Api/appsettings.json @@ -7,9 +7,6 @@ "LogTemplate": "{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", "ElasticUri": "http://localhost:9200" }, - "ConnectionStrings": { - "DefaultConnection": "Server=.\\sqlexpress;Database=BookingDB;Trusted_Connection=True;MultipleActiveResultSets=true" - }, "Jwt": { "Authority": "https://localhost:5005", "Audience": "booking-api" @@ -27,9 +24,14 @@ "EventStore": { "ConnectionString": "esdb://localhost:2113?tls=false" }, + "MongoOptions": { + "ConnectionString": "mongodb://localhost:27017", + "DatabaseName": "booking-db" + }, "PersistMessageOptions": { "Interval": 30, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageDB;Trusted_Connection=True;MultipleActiveResultSets=true" }, "AllowedHosts": "*" } diff --git a/src/Services/Booking/src/Booking.Api/appsettings.test.json b/src/Services/Booking/src/Booking.Api/appsettings.test.json index c61ce0a..6b67e94 100644 --- a/src/Services/Booking/src/Booking.Api/appsettings.test.json +++ b/src/Services/Booking/src/Booking.Api/appsettings.test.json @@ -18,6 +18,11 @@ }, "PersistMessageOptions": { "Interval": 1, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageTestDB;Trusted_Connection=True;MultipleActiveResultSets=true" + }, + "MongoOptions": { + "ConnectionString": "mongodb://localhost:27017", + "DatabaseName": "booking-db-test" } } diff --git a/src/Services/Booking/src/Booking/Booking.csproj b/src/Services/Booking/src/Booking/Booking.csproj index e15133a..84f2ebf 100644 --- a/src/Services/Booking/src/Booking/Booking.csproj +++ b/src/Services/Booking/src/Booking/Booking.csproj @@ -11,10 +11,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/src/Services/Booking/src/Booking/Booking/Events/Domain/BookingCreatedDomainEvent.cs b/src/Services/Booking/src/Booking/Booking/Events/Domain/BookingCreatedDomainEvent.cs index c15112c..9533ffe 100644 --- a/src/Services/Booking/src/Booking/Booking/Events/Domain/BookingCreatedDomainEvent.cs +++ b/src/Services/Booking/src/Booking/Booking/Events/Domain/BookingCreatedDomainEvent.cs @@ -1,6 +1,7 @@ using Booking.Booking.Models.ValueObjects; using BuildingBlocks.Core.Event; +using BuildingBlocks.Core.Model; namespace Booking.Booking.Events.Domain; -public record BookingCreatedDomainEvent(long Id, PassengerInfo PassengerInfo, Trip Trip, bool IsDeleted) : IDomainEvent; +public record BookingCreatedDomainEvent(long Id, PassengerInfo PassengerInfo, Trip Trip) : Audit, IDomainEvent; diff --git a/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs b/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs index b47bce0..e190aeb 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/BookingMappings.cs @@ -1,4 +1,7 @@ using Booking.Booking.Dtos; +using Booking.Booking.Events.Domain; +using Booking.Booking.Models.Reads; +using BuildingBlocks.IdsGenerator; using Mapster; namespace Booking.Booking.Features; diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommand.cs b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommand.cs index d48196e..f041564 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommand.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommand.cs @@ -1,9 +1,10 @@ using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using BuildingBlocks.IdsGenerator; namespace Booking.Booking.Features.CreateBooking; -public record CreateBookingCommand(long PassengerId, long FlightId, string Description) : ICommand +public record CreateBookingCommand(long PassengerId, long FlightId, string Description) : ICommand, IInternalCommand { public long Id { get; init; } = SnowFlakIdGenerator.NewId(); } diff --git a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs index 2c60f0f..0a595f7 100644 --- a/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs +++ b/src/Services/Booking/src/Booking/Booking/Features/CreateBooking/CreateBookingCommandHandler.cs @@ -1,10 +1,11 @@ using Ardalis.GuardClauses; +using Booking.Booking.Events.Domain; using Booking.Booking.Exceptions; using Booking.Booking.Models.ValueObjects; using BuildingBlocks.Contracts.Grpc; using BuildingBlocks.Core.CQRS; using BuildingBlocks.EventStoreDB.Repository; -using MediatR; +using BuildingBlocks.Utils; namespace Booking.Booking.Features.CreateBooking; @@ -12,15 +13,18 @@ public class CreateBookingCommandHandler : ICommandHandler _eventStoreDbRepository; private readonly IFlightGrpcService _flightGrpcService; + private readonly ICurrentUserProvider _currentUserProvider; private readonly IPassengerGrpcService _passengerGrpcService; public CreateBookingCommandHandler(IEventStoreDBRepository eventStoreDbRepository, IPassengerGrpcService passengerGrpcService, - IFlightGrpcService flightGrpcService) + IFlightGrpcService flightGrpcService, + ICurrentUserProvider currentUserProvider) { _eventStoreDbRepository = eventStoreDbRepository; _passengerGrpcService = passengerGrpcService; _flightGrpcService = flightGrpcService; + _currentUserProvider = currentUserProvider; } public async Task Handle(CreateBookingCommand command, @@ -44,11 +48,12 @@ public class CreateBookingCommandHandler : ICommandHandler +public record Booking : AggregateEventSourcing { - public Booking() - { - } - public Trip Trip { get; private set; } public PassengerInfo PassengerInfo { get; private set; } - public static Booking Create(long id, PassengerInfo passengerInfo, Trip trip, bool isDeleted = false) + public static Booking Create(long id, PassengerInfo passengerInfo, Trip trip, bool isDeleted = false, long? userId = null) { - var booking = new Booking() - { - Id = id, - Trip = trip, - PassengerInfo = passengerInfo, - IsDeleted = isDeleted - }; + var booking = new Booking { Id = id, Trip = trip, PassengerInfo = passengerInfo, IsDeleted = isDeleted }; - var @event = new BookingCreatedDomainEvent(booking.Id, booking.PassengerInfo, booking.Trip, booking.IsDeleted); + var @event = new BookingCreatedDomainEvent(booking.Id, booking.PassengerInfo, booking.Trip) + { + IsDeleted = booking.IsDeleted, + CreatedAt = DateTime.Now, + CreatedBy = userId + }; booking.AddDomainEvent(@event); booking.Apply(@event); @@ -35,9 +32,9 @@ public class Booking : AggregateEventSourcing { switch (@event) { - case BookingCreatedDomainEvent reservationCreated: + case BookingCreatedDomainEvent bookingCreated: { - Apply(reservationCreated); + Apply(bookingCreated); return; } } diff --git a/src/Services/Booking/src/Booking/Booking/Models/Reads/BookingReadModel.cs b/src/Services/Booking/src/Booking/Booking/Models/Reads/BookingReadModel.cs new file mode 100644 index 0000000..7ec381c --- /dev/null +++ b/src/Services/Booking/src/Booking/Booking/Models/Reads/BookingReadModel.cs @@ -0,0 +1,12 @@ +using Booking.Booking.Models.ValueObjects; + +namespace Booking.Booking.Models.Reads; + +public class BookingReadModel +{ + public long Id { get; init; } + public long BookId { get; init; } + public Trip Trip { get; init; } + public PassengerInfo PassengerInfo { get; init; } + public bool IsDeleted { get; init; } +} diff --git a/src/Services/Booking/src/Booking/BookingProjection.cs b/src/Services/Booking/src/Booking/BookingProjection.cs index d046a5e..e9402fe 100644 --- a/src/Services/Booking/src/Booking/BookingProjection.cs +++ b/src/Services/Booking/src/Booking/BookingProjection.cs @@ -1,19 +1,22 @@ using Booking.Booking.Events.Domain; +using Booking.Booking.Models.Reads; using Booking.Data; using BuildingBlocks.EventStoreDB.Events; using BuildingBlocks.EventStoreDB.Projections; +using BuildingBlocks.IdsGenerator; using MediatR; -using Microsoft.EntityFrameworkCore; +using MongoDB.Driver; +using MongoDB.Driver.Linq; namespace Booking; public class BookingProjection : IProjectionProcessor { - private readonly BookingDbContext _bookingDbContext; + private readonly BookingReadDbContext _bookingReadDbContext; - public BookingProjection(BookingDbContext bookingDbContext) + public BookingProjection(BookingReadDbContext bookingReadDbContext) { - _bookingDbContext = bookingDbContext; + _bookingReadDbContext = bookingReadDbContext; } public async Task ProcessEventAsync(StreamEvent streamEvent, CancellationToken cancellationToken = default) @@ -21,8 +24,8 @@ public class BookingProjection : IProjectionProcessor { switch (streamEvent.Data) { - case BookingCreatedDomainEvent reservationCreatedDomainEvent: - await Apply(reservationCreatedDomainEvent, cancellationToken); + case BookingCreatedDomainEvent bookingCreatedDomainEvent: + await Apply(bookingCreatedDomainEvent, cancellationToken); break; } } @@ -30,15 +33,21 @@ public class BookingProjection : IProjectionProcessor private async Task Apply(BookingCreatedDomainEvent @event, CancellationToken cancellationToken = default) { var reservation = - await _bookingDbContext.Bookings.SingleOrDefaultAsync(x => x.Id == @event.Id, + await _bookingReadDbContext.Booking.AsQueryable().SingleOrDefaultAsync(x => x.Id == @event.Id && !x.IsDeleted, cancellationToken); if (reservation == null) { - var model = Booking.Models.Booking.Create(@event.Id, @event.PassengerInfo, @event.Trip, @event.IsDeleted); + var bookingReadModel = new BookingReadModel + { + Id = SnowFlakIdGenerator.NewId(), + Trip = @event.Trip, + BookId = @event.Id, + PassengerInfo = @event.PassengerInfo, + IsDeleted = @event.IsDeleted + }; - await _bookingDbContext.Set().AddAsync(model, cancellationToken); - await _bookingDbContext.SaveChangesAsync(cancellationToken); + await _bookingReadDbContext.Booking.InsertOneAsync(bookingReadModel, cancellationToken: cancellationToken); } } } diff --git a/src/Services/Booking/src/Booking/Data/BookingDbContext.cs b/src/Services/Booking/src/Booking/Data/BookingDbContext.cs deleted file mode 100644 index 14b59b9..0000000 --- a/src/Services/Booking/src/Booking/Data/BookingDbContext.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Reflection; -using BuildingBlocks.EFCore; -using Microsoft.AspNetCore.Http; -using Microsoft.EntityFrameworkCore; - -namespace Booking.Data; - -public class BookingDbContext : AppDbContextBase -{ - public const string DefaultSchema = "dbo"; - - public BookingDbContext(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base(options, httpContextAccessor) - { - } - - public DbSet Bookings => Set(); - - protected override void OnModelCreating(ModelBuilder builder) - { - builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); - base.OnModelCreating(builder); - } -} diff --git a/src/Services/Booking/src/Booking/Data/BookingReadDbContext.cs b/src/Services/Booking/src/Booking/Data/BookingReadDbContext.cs new file mode 100644 index 0000000..071244f --- /dev/null +++ b/src/Services/Booking/src/Booking/Data/BookingReadDbContext.cs @@ -0,0 +1,17 @@ +using Booking.Booking.Models.Reads; +using BuildingBlocks.Mongo; +using Humanizer; +using Microsoft.Extensions.Options; +using MongoDB.Driver; + +namespace Booking.Data; + +public class BookingReadDbContext : MongoDbContext +{ + public BookingReadDbContext(IOptions options) : base(options) + { + Booking = GetCollection(nameof(Booking).Underscore()); + } + + public IMongoCollection Booking { get; } +} diff --git a/src/Services/Booking/src/Booking/Data/Configurations/BookingConfiguration.cs b/src/Services/Booking/src/Booking/Data/Configurations/BookingConfiguration.cs deleted file mode 100644 index cedaf72..0000000 --- a/src/Services/Booking/src/Booking/Data/Configurations/BookingConfiguration.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Booking.Data.Configurations; - -public class BookingConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("Booking", BookingDbContext.DefaultSchema); - - builder.HasKey(r => r.Id); - builder.Property(r => r.Id).ValueGeneratedNever(); - - builder.OwnsOne(c => c.Trip, x => - { - x.Property(c => c.Description); - x.Property(c => c.Price); - x.Property(c => c.AircraftId); - x.Property(c => c.FlightDate); - x.Property(c => c.FlightNumber); - x.Property(c => c.SeatNumber); - x.Property(c => c.ArriveAirportId); - x.Property(c => c.DepartureAirportId); - }); - - builder.OwnsOne(c => c.PassengerInfo, x => - { - x.Property(c => c.Name); - }); - } -} diff --git a/src/Services/Booking/src/Booking/Data/DesignTimeDbContextFactory.cs b/src/Services/Booking/src/Booking/Data/DesignTimeDbContextFactory.cs deleted file mode 100644 index 488c53d..0000000 --- a/src/Services/Booking/src/Booking/Data/DesignTimeDbContextFactory.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Design; - -namespace Booking.Data; - -public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory -{ - public BookingDbContext CreateDbContext(string[] args) - { - var builder = new DbContextOptionsBuilder(); - - builder.UseSqlServer( - "Data Source=.\\sqlexpress;Initial Catalog=BookingDB;Persist Security Info=False;Integrated Security=SSPI"); - return new BookingDbContext(builder.Options, null); - } -} diff --git a/src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.Designer.cs b/src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.Designer.cs deleted file mode 100644 index cd3f373..0000000 --- a/src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.Designer.cs +++ /dev/null @@ -1,117 +0,0 @@ -// -using System; -using Booking.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Booking.Data.Migrations -{ - [DbContext(typeof(BookingDbContext))] - [Migration("20220507150115_initial")] - partial class initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("Booking.Booking.Models.Booking", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("Booking", "dbo"); - }); - - modelBuilder.Entity("Booking.Booking.Models.Booking", b => - { - b.OwnsOne("Booking.Booking.Models.ValueObjects.PassengerInfo", "PassengerInfo", b1 => - { - b1.Property("BookingId") - .HasColumnType("bigint"); - - b1.Property("Name") - .HasColumnType("nvarchar(max)"); - - b1.HasKey("BookingId"); - - b1.ToTable("Booking", "dbo"); - - b1.WithOwner() - .HasForeignKey("BookingId"); - }); - - b.OwnsOne("Booking.Booking.Models.ValueObjects.Trip", "Trip", b1 => - { - b1.Property("BookingId") - .HasColumnType("bigint"); - - b1.Property("AircraftId") - .HasColumnType("bigint"); - - b1.Property("ArriveAirportId") - .HasColumnType("bigint"); - - b1.Property("DepartureAirportId") - .HasColumnType("bigint"); - - b1.Property("Description") - .HasColumnType("nvarchar(max)"); - - b1.Property("FlightDate") - .HasColumnType("datetime2"); - - b1.Property("FlightNumber") - .HasColumnType("nvarchar(max)"); - - b1.Property("Price") - .HasColumnType("decimal(18,2)"); - - b1.Property("SeatNumber") - .HasColumnType("nvarchar(max)"); - - b1.HasKey("BookingId"); - - b1.ToTable("Booking", "dbo"); - - b1.WithOwner() - .HasForeignKey("BookingId"); - }); - - b.Navigation("PassengerInfo"); - - b.Navigation("Trip"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.cs b/src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.cs deleted file mode 100644 index d93dc16..0000000 --- a/src/Services/Booking/src/Booking/Data/Migrations/20220507150115_initial.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Booking.Data.Migrations -{ - public partial class initial : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "dbo"); - - migrationBuilder.CreateTable( - name: "Booking", - schema: "dbo", - columns: table => new - { - Id = table.Column(type: "bigint", nullable: false), - Trip_FlightNumber = table.Column(type: "nvarchar(max)", nullable: true), - Trip_AircraftId = table.Column(type: "bigint", nullable: true), - Trip_DepartureAirportId = table.Column(type: "bigint", nullable: true), - Trip_ArriveAirportId = table.Column(type: "bigint", nullable: true), - Trip_FlightDate = table.Column(type: "datetime2", nullable: true), - Trip_Price = table.Column(type: "decimal(18,2)", nullable: true), - Trip_Description = table.Column(type: "nvarchar(max)", nullable: true), - Trip_SeatNumber = table.Column(type: "nvarchar(max)", nullable: true), - PassengerInfo_Name = table.Column(type: "nvarchar(max)", nullable: true), - CreatedAt = table.Column(type: "datetime2", nullable: true), - CreatedBy = table.Column(type: "bigint", nullable: true), - LastModified = table.Column(type: "datetime2", nullable: true), - LastModifiedBy = table.Column(type: "bigint", nullable: true), - Version = table.Column(type: "bigint", nullable: false), - IsDeleted = table.Column(type: "bit", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Booking", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Booking", - schema: "dbo"); - } - } -} diff --git a/src/Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.Designer.cs b/src/Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.Designer.cs deleted file mode 100644 index 1ed4593..0000000 --- a/src/Services/Booking/src/Booking/Data/Migrations/20220616121920_Add-PersistMessages.Designer.cs +++ /dev/null @@ -1,152 +0,0 @@ -// -using System; -using Booking.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Booking.Data.Migrations -{ - [DbContext(typeof(BookingDbContext))] - [Migration("20220616121920_Add-PersistMessages")] - partial class AddPersistMessages - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("Booking.Booking.Models.Booking", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("Booking", "dbo"); - }); - - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .HasColumnType("nvarchar(max)"); - - b.Property("DataType") - .HasColumnType("nvarchar(max)"); - - b.Property("DeliveryType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("MessageStatus") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("RetryCount") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("PersistMessages", "dbo"); - }); - - modelBuilder.Entity("Booking.Booking.Models.Booking", b => - { - b.OwnsOne("Booking.Booking.Models.ValueObjects.PassengerInfo", "PassengerInfo", b1 => - { - b1.Property("BookingId") - .HasColumnType("bigint"); - - b1.Property("Name") - .HasColumnType("nvarchar(max)"); - - b1.HasKey("BookingId"); - - b1.ToTable("Booking", "dbo"); - - b1.WithOwner() - .HasForeignKey("BookingId"); - }); - - b.OwnsOne("Booking.Booking.Models.ValueObjects.Trip", "Trip", b1 => - { - b1.Property("BookingId") - .HasColumnType("bigint"); - - b1.Property("AircraftId") - .HasColumnType("bigint"); - - b1.Property("ArriveAirportId") - .HasColumnType("bigint"); - - b1.Property("DepartureAirportId") - .HasColumnType("bigint"); - - b1.Property("Description") - .HasColumnType("nvarchar(max)"); - - b1.Property("FlightDate") - .HasColumnType("datetime2"); - - b1.Property("FlightNumber") - .HasColumnType("nvarchar(max)"); - - b1.Property("Price") - .HasColumnType("decimal(18,2)"); - - b1.Property("SeatNumber") - .HasColumnType("nvarchar(max)"); - - b1.HasKey("BookingId"); - - b1.ToTable("Booking", "dbo"); - - b1.WithOwner() - .HasForeignKey("BookingId"); - }); - - b.Navigation("PassengerInfo"); - - b.Navigation("Trip"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Booking/src/Booking/Data/Migrations/BookingDbContextModelSnapshot.cs b/src/Services/Booking/src/Booking/Data/Migrations/BookingDbContextModelSnapshot.cs deleted file mode 100644 index bc24711..0000000 --- a/src/Services/Booking/src/Booking/Data/Migrations/BookingDbContextModelSnapshot.cs +++ /dev/null @@ -1,150 +0,0 @@ -// -using System; -using Booking.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Booking.Data.Migrations -{ - [DbContext(typeof(BookingDbContext))] - partial class BookingDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("Booking.Booking.Models.Booking", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("Booking", "dbo"); - }); - - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .HasColumnType("nvarchar(max)"); - - b.Property("DataType") - .HasColumnType("nvarchar(max)"); - - b.Property("DeliveryType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("MessageStatus") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("RetryCount") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("PersistMessages", "dbo"); - }); - - modelBuilder.Entity("Booking.Booking.Models.Booking", b => - { - b.OwnsOne("Booking.Booking.Models.ValueObjects.PassengerInfo", "PassengerInfo", b1 => - { - b1.Property("BookingId") - .HasColumnType("bigint"); - - b1.Property("Name") - .HasColumnType("nvarchar(max)"); - - b1.HasKey("BookingId"); - - b1.ToTable("Booking", "dbo"); - - b1.WithOwner() - .HasForeignKey("BookingId"); - }); - - b.OwnsOne("Booking.Booking.Models.ValueObjects.Trip", "Trip", b1 => - { - b1.Property("BookingId") - .HasColumnType("bigint"); - - b1.Property("AircraftId") - .HasColumnType("bigint"); - - b1.Property("ArriveAirportId") - .HasColumnType("bigint"); - - b1.Property("DepartureAirportId") - .HasColumnType("bigint"); - - b1.Property("Description") - .HasColumnType("nvarchar(max)"); - - b1.Property("FlightDate") - .HasColumnType("datetime2"); - - b1.Property("FlightNumber") - .HasColumnType("nvarchar(max)"); - - b1.Property("Price") - .HasColumnType("decimal(18,2)"); - - b1.Property("SeatNumber") - .HasColumnType("nvarchar(max)"); - - b1.HasKey("BookingId"); - - b1.ToTable("Booking", "dbo"); - - b1.WithOwner() - .HasForeignKey("BookingId"); - }); - - b.Navigation("PassengerInfo"); - - b.Navigation("Trip"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Booking/src/Booking/Data/readme.md b/src/Services/Booking/src/Booking/Data/readme.md deleted file mode 100644 index 4ab73f7..0000000 --- a/src/Services/Booking/src/Booking/Data/readme.md +++ /dev/null @@ -1,2 +0,0 @@ -dotnet ef migrations add initial --context BookingDbContext -o "Data\Migrations" -dotnet ef database update --context BookingDbContext diff --git a/src/Services/Booking/src/Booking/EventMapper.cs b/src/Services/Booking/src/Booking/EventMapper.cs index 2435c35..84f743e 100644 --- a/src/Services/Booking/src/Booking/EventMapper.cs +++ b/src/Services/Booking/src/Booking/EventMapper.cs @@ -16,7 +16,7 @@ public sealed class EventMapper : IEventMapper }; } - public InternalCommand MapToInternalCommand(IDomainEvent @event) + public IInternalCommand MapToInternalCommand(IDomainEvent @event) { return @event switch { diff --git a/src/Services/Booking/src/Booking/Extensions/CoreExtensions.cs b/src/Services/Booking/src/Booking/Extensions/CoreExtensions.cs new file mode 100644 index 0000000..beaf121 --- /dev/null +++ b/src/Services/Booking/src/Booking/Extensions/CoreExtensions.cs @@ -0,0 +1,17 @@ +using BuildingBlocks.Core; +using BuildingBlocks.Utils; +using Microsoft.Extensions.DependencyInjection; + +namespace Booking.Extensions; + +public static class CoreExtensions +{ + public static IServiceCollection AddCore(this IServiceCollection services) + { + services.AddScoped(); + services.AddTransient(); + services.AddScoped(); + + return services; + } +} diff --git a/src/Services/Booking/src/Booking/Extensions/MediatRExtensions.cs b/src/Services/Booking/src/Booking/Extensions/MediatRExtensions.cs index 8586739..72514c7 100644 --- a/src/Services/Booking/src/Booking/Extensions/MediatRExtensions.cs +++ b/src/Services/Booking/src/Booking/Extensions/MediatRExtensions.cs @@ -13,7 +13,6 @@ public static class MediatRExtensions services.AddMediatR(typeof(BookingRoot).Assembly); services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); - services.AddScoped(typeof(IPipelineBehavior<,>), typeof(EfTxBehavior<,>)); return services; } diff --git a/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs b/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs index a407148..6f4d91b 100644 --- a/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs +++ b/src/Services/Booking/tests/IntegrationTest/Booking/Features/CreateBookingTests.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using Booking.Booking.Models.Reads; using Booking.Data; using BuildingBlocks.Contracts.Grpc; +using BuildingBlocks.PersistMessageProcessor.Data; using BuildingBlocks.TestBase; using FluentAssertions; using Integration.Test.Fakes; @@ -14,9 +16,10 @@ using Xunit; namespace Integration.Test.Booking.Features; -public class CreateBookingTests : IntegrationTestBase +public class CreateBookingTests : IntegrationTestBase { - public CreateBookingTests(IntegrationTestFixture integrationTestFixture) : base( + public CreateBookingTests( + IntegrationTestFixture integrationTestFixture) : base( integrationTestFixture) { } diff --git a/src/Services/Flight/src/Flight.Api/Program.cs b/src/Services/Flight/src/Flight.Api/Program.cs index b771584..975b85e 100644 --- a/src/Services/Flight/src/Flight.Api/Program.cs +++ b/src/Services/Flight/src/Flight.Api/Program.cs @@ -9,9 +9,9 @@ using BuildingBlocks.Jwt; using BuildingBlocks.Logging; using BuildingBlocks.Mapster; using BuildingBlocks.MassTransit; -using BuildingBlocks.MessageProcessor; using BuildingBlocks.Mongo; using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.Swagger; using BuildingBlocks.Web; using Figgle; @@ -37,10 +37,10 @@ builder.Services.AddCustomDbContext(configuration); builder.Services.AddScoped(); builder.Services.AddMongoDbContext(configuration); - builder.Services.AddPersistMessage(configuration); builder.AddCustomSerilog(); +builder.Services.AddCore(); builder.Services.AddJwt(); builder.Services.AddControllers(); builder.Services.AddCustomSwagger(configuration, typeof(FlightRoot).Assembly); @@ -50,7 +50,6 @@ builder.Services.AddValidatorsFromAssembly(typeof(FlightRoot).Assembly); builder.Services.AddCustomProblemDetails(); builder.Services.AddCustomMapster(typeof(FlightRoot).Assembly); builder.Services.AddHttpContextAccessor(); -builder.Services.AddTransient(); builder.Services.AddCustomMassTransit(typeof(FlightRoot).Assembly, env); builder.Services.AddCustomOpenTelemetry(); builder.Services.AddRouting(options => options.LowercaseUrls = true); diff --git a/src/Services/Flight/src/Flight.Api/appsettings.json b/src/Services/Flight/src/Flight.Api/appsettings.json index 5f5443c..eabc956 100644 --- a/src/Services/Flight/src/Flight.Api/appsettings.json +++ b/src/Services/Flight/src/Flight.Api/appsettings.json @@ -26,7 +26,8 @@ }, "PersistMessageOptions": { "Interval": 30, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageDB;Trusted_Connection=True;MultipleActiveResultSets=true" }, "AllowedHosts": "*" } diff --git a/src/Services/Flight/src/Flight.Api/appsettings.test.json b/src/Services/Flight/src/Flight.Api/appsettings.test.json index 4e0aab5..dee31b4 100644 --- a/src/Services/Flight/src/Flight.Api/appsettings.test.json +++ b/src/Services/Flight/src/Flight.Api/appsettings.test.json @@ -18,6 +18,7 @@ }, "PersistMessageOptions": { "Interval": 1, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageTestDB;Trusted_Connection=True;MultipleActiveResultSets=true" } } diff --git a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/CreateAircraftCommand.cs b/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/CreateAircraftCommand.cs index 7bdf1bc..f9fc9db 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/CreateAircraftCommand.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Features/CreateAircraft/CreateAircraftCommand.cs @@ -1,4 +1,5 @@ using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using BuildingBlocks.IdsGenerator; using Flight.Aircrafts.Dtos; using MediatR; diff --git a/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs b/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs index 91cb225..f5c17bd 100644 --- a/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs +++ b/src/Services/Flight/src/Flight/Aircrafts/Models/Aircraft.cs @@ -4,7 +4,7 @@ using Flight.Aircrafts.Events; namespace Flight.Aircrafts.Models; -public class Aircraft : Aggregate +public record Aircraft : Aggregate { public Aircraft() { diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/CreateAirportCommand.cs b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/CreateAirportCommand.cs index 88eebae..9196892 100644 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/CreateAirportCommand.cs +++ b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/CreateAirportCommand.cs @@ -1,4 +1,5 @@ using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using BuildingBlocks.IdsGenerator; using Flight.Airports.Dtos; using MediatR; diff --git a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Reads/CreateAirportMongoCommand.cs b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Reads/CreateAirportMongoCommand.cs index f67988a..658f5ce 100644 --- a/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Reads/CreateAirportMongoCommand.cs +++ b/src/Services/Flight/src/Flight/Airports/Features/CreateAirport/Reads/CreateAirportMongoCommand.cs @@ -13,7 +13,6 @@ public class CreateAirportMongoCommand : InternalCommand IsDeleted = isDeleted; } - public long Id { get; } public string Name { get; } public string Address { get; } public string Code { get; } diff --git a/src/Services/Flight/src/Flight/Airports/Models/Airport.cs b/src/Services/Flight/src/Flight/Airports/Models/Airport.cs index 2dcc4b0..a6e6b46 100644 --- a/src/Services/Flight/src/Flight/Airports/Models/Airport.cs +++ b/src/Services/Flight/src/Flight/Airports/Models/Airport.cs @@ -4,7 +4,7 @@ using Flight.Airports.Events; namespace Flight.Airports.Models; -public class Airport : Aggregate +public record Airport : Aggregate { public Airport() { diff --git a/src/Services/Flight/src/Flight/Data/Configurations/PersistMessageConfiguration.cs b/src/Services/Flight/src/Flight/Data/Configurations/PersistMessageConfiguration.cs deleted file mode 100644 index e9455c9..0000000 --- a/src/Services/Flight/src/Flight/Data/Configurations/PersistMessageConfiguration.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using BuildingBlocks.MessageProcessor; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Flight.Data.Configurations; - -public class PersistMessageConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("PersistMessages", FlightDbContext.DefaultSchema); - - builder.HasKey(x => x.Id); - - builder.Property(x => x.Id) - .IsRequired(); - - builder.Property(x => x.DeliveryType) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageDeliveryType)Enum.Parse(typeof(MessageDeliveryType), v)) - .IsRequired() - .IsUnicode(false); - - builder.Property(x => x.DeliveryType) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageDeliveryType)Enum.Parse(typeof(MessageDeliveryType), v)) - .IsRequired() - .IsUnicode(false); - - builder.Property(x => x.MessageStatus) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageStatus)Enum.Parse(typeof(MessageStatus), v)) - .IsRequired() - .IsUnicode(false); - } -} diff --git a/src/Services/Flight/src/Flight/Data/FlightDbContext.cs b/src/Services/Flight/src/Flight/Data/FlightDbContext.cs index 33d3386..29dcb87 100644 --- a/src/Services/Flight/src/Flight/Data/FlightDbContext.cs +++ b/src/Services/Flight/src/Flight/Data/FlightDbContext.cs @@ -1,5 +1,6 @@ using System.Reflection; using BuildingBlocks.EFCore; +using BuildingBlocks.Utils; using Flight.Aircrafts.Models; using Flight.Airports.Models; using Flight.Seats.Models; @@ -11,8 +12,8 @@ namespace Flight.Data; public sealed class FlightDbContext : AppDbContextBase { public const string DefaultSchema = "dbo"; - public FlightDbContext(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base( - options, httpContextAccessor) + public FlightDbContext(DbContextOptions options, ICurrentUserProvider currentUserProvider) : base( + options, currentUserProvider) { } @@ -24,7 +25,7 @@ public sealed class FlightDbContext : AppDbContextBase protected override void OnModelCreating(ModelBuilder builder) { builder.FilterSoftDeletedProperties(); - builder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly()); + builder.ApplyConfigurationsFromAssembly(typeof(FlightRoot).Assembly); base.OnModelCreating(builder); } } diff --git a/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs b/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs index e1b4540..d5c4d40 100644 --- a/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs +++ b/src/Services/Flight/src/Flight/Data/FlightReadDbContext.cs @@ -1,6 +1,5 @@ using BuildingBlocks.Mongo; using Flight.Aircrafts.Models.Reads; -using Flight.Airports.Models; using Flight.Airports.Models.Reads; using Flight.Flights.Models.Reads; using Flight.Seats.Models.Reads; diff --git a/src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.Designer.cs b/src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.Designer.cs deleted file mode 100644 index b5c33cf..0000000 --- a/src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.Designer.cs +++ /dev/null @@ -1,266 +0,0 @@ -// -using System; -using Flight.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Flight.Data.Migrations -{ - [DbContext(typeof(FlightDbContext))] - [Migration("20220616121204_Add-PersistMessages")] - partial class AddPersistMessages - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .HasColumnType("nvarchar(max)"); - - b.Property("DataType") - .HasColumnType("nvarchar(max)"); - - b.Property("DeliveryType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("MessageStatus") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("RetryCount") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("PersistMessages", "dbo"); - }); - - modelBuilder.Entity("Flight.Aircrafts.Models.Aircraft", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("ManufacturingYear") - .HasColumnType("int"); - - b.Property("Model") - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("Aircraft", "dbo"); - }); - - modelBuilder.Entity("Flight.Airports.Models.Airport", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("Address") - .HasColumnType("nvarchar(max)"); - - b.Property("Code") - .HasColumnType("nvarchar(max)"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("Name") - .HasColumnType("nvarchar(max)"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.ToTable("Airport", "dbo"); - }); - - modelBuilder.Entity("Flight.Flights.Models.Flight", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("AircraftId") - .HasColumnType("bigint"); - - b.Property("ArriveAirportId") - .HasColumnType("bigint"); - - b.Property("ArriveDate") - .HasColumnType("datetime2"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("DepartureAirportId") - .HasColumnType("bigint"); - - b.Property("DepartureDate") - .HasColumnType("datetime2"); - - b.Property("DurationMinutes") - .HasColumnType("decimal(18,2)"); - - b.Property("FlightDate") - .HasColumnType("datetime2"); - - b.Property("FlightNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("Price") - .HasColumnType("decimal(18,2)"); - - b.Property("Status") - .HasColumnType("int"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("AircraftId"); - - b.HasIndex("ArriveAirportId"); - - b.ToTable("Flight", "dbo"); - }); - - modelBuilder.Entity("Flight.Seats.Models.Seat", b => - { - b.Property("Id") - .HasColumnType("bigint"); - - b.Property("Class") - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime2"); - - b.Property("CreatedBy") - .HasColumnType("bigint"); - - b.Property("FlightId") - .HasColumnType("bigint"); - - b.Property("IsDeleted") - .HasColumnType("bit"); - - b.Property("LastModified") - .HasColumnType("datetime2"); - - b.Property("LastModifiedBy") - .HasColumnType("bigint"); - - b.Property("SeatNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("Type") - .HasColumnType("int"); - - b.Property("Version") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("FlightId"); - - b.ToTable("Seat", "dbo"); - }); - - modelBuilder.Entity("Flight.Flights.Models.Flight", b => - { - b.HasOne("Flight.Aircrafts.Models.Aircraft", null) - .WithMany() - .HasForeignKey("AircraftId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Flight.Airports.Models.Airport", null) - .WithMany() - .HasForeignKey("ArriveAirportId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Flight.Seats.Models.Seat", b => - { - b.HasOne("Flight.Flights.Models.Flight", null) - .WithMany() - .HasForeignKey("FlightId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.cs b/src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.cs deleted file mode 100644 index 64a5739..0000000 --- a/src/Services/Flight/src/Flight/Data/Migrations/20220616121204_Add-PersistMessages.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Flight.Data.Migrations -{ - public partial class AddPersistMessages : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "PersistMessages", - schema: "dbo", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - DataType = table.Column(type: "nvarchar(max)", nullable: true), - Data = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - RetryCount = table.Column(type: "int", nullable: false), - MessageStatus = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false), - DeliveryType = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistMessages", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "PersistMessages", - schema: "dbo"); - } - } -} diff --git a/src/Services/Flight/src/Flight/Data/Migrations/20220511215248_Init.Designer.cs b/src/Services/Flight/src/Flight/Data/Migrations/20220728175834_Init.Designer.cs similarity index 99% rename from src/Services/Flight/src/Flight/Data/Migrations/20220511215248_Init.Designer.cs rename to src/Services/Flight/src/Flight/Data/Migrations/20220728175834_Init.Designer.cs index 27ccb3a..349fc42 100644 --- a/src/Services/Flight/src/Flight/Data/Migrations/20220511215248_Init.Designer.cs +++ b/src/Services/Flight/src/Flight/Data/Migrations/20220728175834_Init.Designer.cs @@ -12,7 +12,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Flight.Data.Migrations { [DbContext(typeof(FlightDbContext))] - [Migration("20220511215248_Init")] + [Migration("20220728175834_Init")] partial class Init { protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/src/Services/Flight/src/Flight/Data/Migrations/20220511215248_Init.cs b/src/Services/Flight/src/Flight/Data/Migrations/20220728175834_Init.cs similarity index 98% rename from src/Services/Flight/src/Flight/Data/Migrations/20220511215248_Init.cs rename to src/Services/Flight/src/Flight/Data/Migrations/20220728175834_Init.cs index 1cee26d..5cd66bb 100644 --- a/src/Services/Flight/src/Flight/Data/Migrations/20220511215248_Init.cs +++ b/src/Services/Flight/src/Flight/Data/Migrations/20220728175834_Init.cs @@ -25,8 +25,8 @@ namespace Flight.Data.Migrations CreatedBy = table.Column(type: "bigint", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), LastModifiedBy = table.Column(type: "bigint", nullable: true), - Version = table.Column(type: "bigint", nullable: false), - IsDeleted = table.Column(type: "bit", nullable: false) + IsDeleted = table.Column(type: "bit", nullable: false), + Version = table.Column(type: "bigint", nullable: false) }, constraints: table => { @@ -46,8 +46,8 @@ namespace Flight.Data.Migrations CreatedBy = table.Column(type: "bigint", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), LastModifiedBy = table.Column(type: "bigint", nullable: true), - Version = table.Column(type: "bigint", nullable: false), - IsDeleted = table.Column(type: "bit", nullable: false) + IsDeleted = table.Column(type: "bit", nullable: false), + Version = table.Column(type: "bigint", nullable: false) }, constraints: table => { @@ -74,8 +74,8 @@ namespace Flight.Data.Migrations CreatedBy = table.Column(type: "bigint", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), LastModifiedBy = table.Column(type: "bigint", nullable: true), - Version = table.Column(type: "bigint", nullable: false), - IsDeleted = table.Column(type: "bit", nullable: false) + IsDeleted = table.Column(type: "bit", nullable: false), + Version = table.Column(type: "bigint", nullable: false) }, constraints: table => { @@ -110,8 +110,8 @@ namespace Flight.Data.Migrations CreatedBy = table.Column(type: "bigint", nullable: true), LastModified = table.Column(type: "datetime2", nullable: true), LastModifiedBy = table.Column(type: "bigint", nullable: true), - Version = table.Column(type: "bigint", nullable: false), - IsDeleted = table.Column(type: "bit", nullable: false) + IsDeleted = table.Column(type: "bit", nullable: false), + Version = table.Column(type: "bigint", nullable: false) }, constraints: table => { diff --git a/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs b/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs index 730306d..de7d19c 100644 --- a/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs +++ b/src/Services/Flight/src/Flight/Data/Migrations/FlightDbContextModelSnapshot.cs @@ -22,41 +22,6 @@ namespace Flight.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .HasColumnType("nvarchar(max)"); - - b.Property("DataType") - .HasColumnType("nvarchar(max)"); - - b.Property("DeliveryType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("MessageStatus") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("RetryCount") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("PersistMessages", "dbo"); - }); - modelBuilder.Entity("Flight.Aircrafts.Models.Aircraft", b => { b.Property("Id") diff --git a/src/Services/Flight/src/Flight/EventMapper.cs b/src/Services/Flight/src/Flight/EventMapper.cs index 44a6894..d0eeb2c 100644 --- a/src/Services/Flight/src/Flight/EventMapper.cs +++ b/src/Services/Flight/src/Flight/EventMapper.cs @@ -33,7 +33,7 @@ public sealed class EventMapper : IEventMapper }; } - public InternalCommand MapToInternalCommand(IDomainEvent @event) + public IInternalCommand MapToInternalCommand(IDomainEvent @event) { return @event switch { diff --git a/src/Services/Flight/src/Flight/Extensions/CoreExtensions.cs b/src/Services/Flight/src/Flight/Extensions/CoreExtensions.cs new file mode 100644 index 0000000..f315d79 --- /dev/null +++ b/src/Services/Flight/src/Flight/Extensions/CoreExtensions.cs @@ -0,0 +1,17 @@ +using BuildingBlocks.Core; +using BuildingBlocks.Utils; +using Microsoft.Extensions.DependencyInjection; + +namespace Flight.Extensions; + +public static class CoreExtensions +{ + public static IServiceCollection AddCore(this IServiceCollection services) + { + services.AddScoped(); + services.AddTransient(); + services.AddScoped(); + + return services; + } +} diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommand.cs index 7cae278..30f1c0f 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommand.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommand.cs @@ -1,5 +1,6 @@ using System; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using BuildingBlocks.IdsGenerator; using Flight.Flights.Dtos; using Flight.Flights.Models; diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommandHandler.cs index 1170079..67b8fa7 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/CreateFlightCommandHandler.cs @@ -2,11 +2,9 @@ using System.Threading; using System.Threading.Tasks; using Ardalis.GuardClauses; using BuildingBlocks.Core.CQRS; -using BuildingBlocks.MessageProcessor; using Flight.Data; using Flight.Flights.Dtos; using Flight.Flights.Exceptions; -using Flight.Flights.Features.CreateFlight.Reads; using MapsterMapper; using Microsoft.EntityFrameworkCore; diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommand.cs index 060e833..43ae679 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommand.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommand.cs @@ -6,23 +6,23 @@ namespace Flight.Flights.Features.CreateFlight.Reads; public class CreateFlightMongoCommand : InternalCommand { - public CreateFlightMongoCommand(long Id, string FlightNumber, long AircraftId, DateTime DepartureDate, - long DepartureAirportId, - DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate, FlightStatus Status, - decimal Price, bool IsDeleted) + public CreateFlightMongoCommand(long id, string flightNumber, long aircraftId, DateTime departureDate, + long departureAirportId, + DateTime arriveDate, long arriveAirportId, decimal durationMinutes, DateTime flightDate, FlightStatus status, + decimal price, bool isDeleted) { - this.Id = Id; - this.FlightNumber = FlightNumber; - this.AircraftId = AircraftId; - this.DepartureDate = DepartureDate; - this.DepartureAirportId = DepartureAirportId; - this.ArriveDate = ArriveDate; - this.ArriveAirportId = ArriveAirportId; - this.DurationMinutes = DurationMinutes; - this.FlightDate = FlightDate; - this.Status = Status; - this.Price = Price; - this.IsDeleted = IsDeleted; + Id = id; + FlightNumber = flightNumber; + AircraftId = aircraftId; + DepartureDate = departureDate; + DepartureAirportId = departureAirportId; + ArriveDate = arriveDate; + ArriveAirportId = arriveAirportId; + DurationMinutes = durationMinutes; + FlightDate = flightDate; + Status = status; + Price = price; + IsDeleted = isDeleted; } public string FlightNumber { get; } diff --git a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommandHandler.cs index 071b542..cbc889c 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/CreateFlight/Reads/CreateFlightMongoCommandHandler.cs @@ -32,7 +32,7 @@ public class CreateFlightMongoCommandHandler : ICommandHandler(command); var flight = await _flightReadDbContext.Flight.AsQueryable() - .FirstOrDefaultAsync(x => x.Id == flightReadModel.Id, cancellationToken); + .FirstOrDefaultAsync(x => x.Id == flightReadModel.Id && !x.IsDeleted, cancellationToken); if (flight is not null) throw new FlightAlreadyExistException(); diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/DeleteFlightCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/DeleteFlightCommand.cs index efa9aaf..d0a44f0 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/DeleteFlightCommand.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/DeleteFlightCommand.cs @@ -1,4 +1,5 @@ using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Flight.Flights.Dtos; namespace Flight.Flights.Features.DeleteFlight; diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommand.cs index 00312a5..5dc6a9b 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommand.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommand.cs @@ -6,23 +6,23 @@ namespace Flight.Flights.Features.DeleteFlight.Reads; public class DeleteFlightMongoCommand : InternalCommand { - public DeleteFlightMongoCommand(long Id, string FlightNumber, long AircraftId, DateTime DepartureDate, - long DepartureAirportId, - DateTime ArriveDate, long ArriveAirportId, decimal DurationMinutes, DateTime FlightDate, FlightStatus Status, - decimal Price, bool IsDeleted) + public DeleteFlightMongoCommand(long id, string flightNumber, long aircraftId, DateTime departureDate, + long departureAirportId, + DateTime arriveDate, long arriveAirportId, decimal durationMinutes, DateTime flightDate, FlightStatus status, + decimal price, bool isDeleted) { - this.Id = Id; - this.FlightNumber = FlightNumber; - this.AircraftId = AircraftId; - this.DepartureDate = DepartureDate; - this.DepartureAirportId = DepartureAirportId; - this.ArriveDate = ArriveDate; - this.ArriveAirportId = ArriveAirportId; - this.DurationMinutes = DurationMinutes; - this.FlightDate = FlightDate; - this.Status = Status; - this.Price = Price; - this.IsDeleted = IsDeleted; + Id = id; + FlightNumber = flightNumber; + AircraftId = aircraftId; + DepartureDate = departureDate; + DepartureAirportId = departureAirportId; + ArriveDate = arriveDate; + ArriveAirportId = arriveAirportId; + DurationMinutes = durationMinutes; + FlightDate = flightDate; + Status = status; + Price = price; + IsDeleted = isDeleted; } public string FlightNumber { get; } diff --git a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommandHandler.cs index b38a98b..f120518 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/DeleteFlight/Reads/DeleteFlightMongoCommandHandler.cs @@ -32,7 +32,7 @@ public class DeleteFlightMongoCommandHandler : ICommandHandler(command); var flight = await _flightReadDbContext.Flight.AsQueryable() - .FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId, cancellationToken); + .FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId && !x.IsDeleted, cancellationToken); if (flight is null) throw new FlightNotFountException(); diff --git a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/GetFlightByIdQueryHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/GetFlightByIdQueryHandler.cs index 0a3acd3..e2cb9ea 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/GetFlightByIdQueryHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/GetFlightById/GetFlightByIdQueryHandler.cs @@ -27,7 +27,8 @@ public class GetFlightByIdQueryHandler : IQueryHandler x.FlightId == query.Id, cancellationToken); + await _flightReadDbContext.Flight.AsQueryable().SingleOrDefaultAsync(x => x.FlightId == query.Id && + !x.IsDeleted, cancellationToken); if (flight is null) throw new FlightNotFountException(); diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Reads/UpdateFlightMongoCommandHandler.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Reads/UpdateFlightMongoCommandHandler.cs index 0857799..ca0fa1e 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Reads/UpdateFlightMongoCommandHandler.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/Reads/UpdateFlightMongoCommandHandler.cs @@ -32,7 +32,7 @@ public class UpdateFlightMongoCommandHandler : ICommandHandler(command); var flight = await _flightReadDbContext.Flight.AsQueryable() - .FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId, cancellationToken); + .FirstOrDefaultAsync(x => x.FlightId == flightReadModel.FlightId && !x.IsDeleted, cancellationToken); if (flight is null) throw new FlightNotFountException(); diff --git a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/UpdateFlightCommand.cs b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/UpdateFlightCommand.cs index 3ad01b1..d636fc2 100644 --- a/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/UpdateFlightCommand.cs +++ b/src/Services/Flight/src/Flight/Flights/Features/UpdateFlight/UpdateFlightCommand.cs @@ -1,6 +1,7 @@ using System; using BuildingBlocks.Caching; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Flight.Flights.Dtos; using Flight.Flights.Models; using MediatR; diff --git a/src/Services/Flight/src/Flight/Flights/Models/Flight.cs b/src/Services/Flight/src/Flight/Flights/Models/Flight.cs index d127a90..b31bcda 100644 --- a/src/Services/Flight/src/Flight/Flights/Models/Flight.cs +++ b/src/Services/Flight/src/Flight/Flights/Models/Flight.cs @@ -4,7 +4,7 @@ using Flight.Flights.Events.Domain; namespace Flight.Flights.Models; -public class Flight : Aggregate +public record Flight : Aggregate { public string FlightNumber { get; private set; } public long AircraftId { get; private set; } diff --git a/src/Services/Flight/src/Flight/Flights/Models/Reads/FlightReadModel.cs b/src/Services/Flight/src/Flight/Flights/Models/Reads/FlightReadModel.cs index b5af62d..8fc26cf 100644 --- a/src/Services/Flight/src/Flight/Flights/Models/Reads/FlightReadModel.cs +++ b/src/Services/Flight/src/Flight/Flights/Models/Reads/FlightReadModel.cs @@ -6,17 +6,17 @@ namespace Flight.Flights.Models.Reads; public class FlightReadModel { - public long Id { get; set; } - public long FlightId { get; set; } - public string FlightNumber { get; set; } - public long AircraftId { get; set; } - public DateTime DepartureDate { get; set; } - public long DepartureAirportId { get; set; } - public DateTime ArriveDate { get; set; } - public long ArriveAirportId { get; set; } - public decimal DurationMinutes { get; set; } - public DateTime FlightDate { get; set; } - public FlightStatus Status { get; set; } - public decimal Price { get; set; } - public bool IsDeleted { get; set; } + public long Id { get; init; } + public long FlightId { get; init; } + public string FlightNumber { get; init; } + public long AircraftId { get; init; } + public DateTime DepartureDate { get; init; } + public long DepartureAirportId { get; init; } + public DateTime ArriveDate { get; init; } + public long ArriveAirportId { get; init; } + public decimal DurationMinutes { get; init; } + public DateTime FlightDate { get; init; } + public FlightStatus Status { get; init; } + public decimal Price { get; init; } + public bool IsDeleted { get; init; } } diff --git a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/CreateSeatCommand.cs b/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/CreateSeatCommand.cs index 800c0ac..b354f9c 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/CreateSeatCommand.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/CreateSeat/CreateSeatCommand.cs @@ -1,4 +1,5 @@ using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using BuildingBlocks.IdsGenerator; using Flight.Seats.Dtos; using Flight.Seats.Models; diff --git a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/GetAvailableSeatsQueryHandler.cs b/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/GetAvailableSeatsQueryHandler.cs index 6901980..199d6e3 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/GetAvailableSeatsQueryHandler.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/GetAvailableSeats/GetAvailableSeatsQueryHandler.cs @@ -29,7 +29,7 @@ public class GetAvailableSeatsQueryHandler : IRequestHandler x.FlightId == query.FlightId); + .Where(x => x.FlightId == query.FlightId && !x.IsDeleted); if (!seats.Any()) throw new AllSeatsFullException(); diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Reads/ReserveSeatMongoCommand.cs b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Reads/ReserveSeatMongoCommand.cs index bb9f5f8..4b8d798 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Reads/ReserveSeatMongoCommand.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/Reads/ReserveSeatMongoCommand.cs @@ -16,7 +16,6 @@ public class ReserveSeatMongoCommand : InternalCommand IsDeleted = isDeleted; } - public long Id { get; } public string SeatNumber { get; } public SeatType Type { get; } public SeatClass Class { get; } diff --git a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/ReserveSeatCommand.cs b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/ReserveSeatCommand.cs index e291523..b63e562 100644 --- a/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/ReserveSeatCommand.cs +++ b/src/Services/Flight/src/Flight/Seats/Features/ReserveSeat/ReserveSeatCommand.cs @@ -1,4 +1,5 @@ using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Flight.Seats.Dtos; namespace Flight.Seats.Features.ReserveSeat; diff --git a/src/Services/Flight/src/Flight/Seats/Models/Seat.cs b/src/Services/Flight/src/Flight/Seats/Models/Seat.cs index 2006556..7bd38a1 100644 --- a/src/Services/Flight/src/Flight/Seats/Models/Seat.cs +++ b/src/Services/Flight/src/Flight/Seats/Models/Seat.cs @@ -5,7 +5,7 @@ using Flight.Seats.Events; namespace Flight.Seats.Models; -public class Seat : Aggregate +public record Seat : Aggregate { public static Seat Create(long id, string seatNumber, SeatType type, SeatClass @class, long flightId, bool isDeleted = false) diff --git a/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs b/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs index cb2eb93..7bf079f 100644 --- a/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs +++ b/src/Services/Flight/tests/UnitTest/Common/DbContextFactory.cs @@ -16,7 +16,7 @@ namespace Unit.Test.Common var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()).Options; - var context = new FlightDbContext(options, httpContextAccessor: null); + var context = new FlightDbContext(options, currentUserProvider: null); // Seed our data FlightDataSeeder(context); diff --git a/src/Services/Flight/tests/UnitTest/Flight/Features/CreateFlight/CreateFlightCommandHandlerTests.cs b/src/Services/Flight/tests/UnitTest/Flight/Features/CreateFlight/CreateFlightCommandHandlerTests.cs index 48f3692..80f053a 100644 --- a/src/Services/Flight/tests/UnitTest/Flight/Features/CreateFlight/CreateFlightCommandHandlerTests.cs +++ b/src/Services/Flight/tests/UnitTest/Flight/Features/CreateFlight/CreateFlightCommandHandlerTests.cs @@ -1,7 +1,6 @@ using System; using System.Threading; using System.Threading.Tasks; -using BuildingBlocks.MessageProcessor; using Flight.Flights.Dtos; using Flight.Flights.Features.CreateFlight; using FluentAssertions; diff --git a/src/Services/Identity/src/Identity.Api/Program.cs b/src/Services/Identity/src/Identity.Api/Program.cs index f6e4c58..2e98509 100644 --- a/src/Services/Identity/src/Identity.Api/Program.cs +++ b/src/Services/Identity/src/Identity.Api/Program.cs @@ -1,11 +1,12 @@ using BuildingBlocks.Core; using BuildingBlocks.EFCore; using BuildingBlocks.HealthCheck; +using BuildingBlocks.IdsGenerator; using BuildingBlocks.Logging; using BuildingBlocks.Mapster; using BuildingBlocks.MassTransit; -using BuildingBlocks.MessageProcessor; using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.Swagger; using BuildingBlocks.Utils; using BuildingBlocks.Web; @@ -27,11 +28,10 @@ var env = builder.Environment; var appOptions = builder.Services.GetOptions("AppOptions"); Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name)); +builder.Services.AddPersistMessage(configuration); builder.Services.AddCustomDbContext(configuration); builder.Services.AddScoped(); - -builder.Services.AddPersistMessage(configuration); - +builder.Services.AddCore(); builder.AddCustomSerilog(); builder.Services.AddControllers(); builder.Services.AddCustomSwagger(configuration, typeof(IdentityRoot).Assembly); @@ -41,11 +41,12 @@ builder.Services.AddValidatorsFromAssembly(typeof(IdentityRoot).Assembly); builder.Services.AddCustomProblemDetails(); builder.Services.AddCustomMapster(typeof(IdentityRoot).Assembly); builder.Services.AddCustomHealthCheck(); -builder.Services.AddTransient(); builder.Services.AddCustomMassTransit(typeof(IdentityRoot).Assembly, env); builder.Services.AddCustomOpenTelemetry(); +SnowFlakIdGenerator.Configure(4); + builder.Services.AddIdentityServer(env); var app = builder.Build(); diff --git a/src/Services/Identity/src/Identity.Api/appsettings.json b/src/Services/Identity/src/Identity.Api/appsettings.json index 645577e..f2fc143 100644 --- a/src/Services/Identity/src/Identity.Api/appsettings.json +++ b/src/Services/Identity/src/Identity.Api/appsettings.json @@ -18,7 +18,8 @@ }, "PersistMessageOptions": { "Interval": 30, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageDB;Trusted_Connection=True;MultipleActiveResultSets=true" }, "AllowedHosts": "*" } diff --git a/src/Services/Identity/src/Identity.Api/appsettings.test.json b/src/Services/Identity/src/Identity.Api/appsettings.test.json index 738f8a4..07d4bdb 100644 --- a/src/Services/Identity/src/Identity.Api/appsettings.test.json +++ b/src/Services/Identity/src/Identity.Api/appsettings.test.json @@ -18,6 +18,7 @@ }, "PersistMessageOptions": { "Interval": 1, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageTestDB;Trusted_Connection=True;MultipleActiveResultSets=true" } } diff --git a/src/Services/Identity/src/Identity.Api/keys/is-signing-key-DBA1A35FADC54B3029F893520A76F5EF.json b/src/Services/Identity/src/Identity.Api/keys/is-signing-key-DBA1A35FADC54B3029F893520A76F5EF.json new file mode 100644 index 0000000..a869c8f --- /dev/null +++ b/src/Services/Identity/src/Identity.Api/keys/is-signing-key-DBA1A35FADC54B3029F893520A76F5EF.json @@ -0,0 +1 @@ +{"Version":1,"Id":"DBA1A35FADC54B3029F893520A76F5EF","Created":"2022-07-28T16:47:11.7018861Z","Algorithm":"RS256","IsX509Certificate":false,"Data":"CfDJ8Pyl4Q0BTFBNj7ITVoMSIQgxsejdUpcAxnjG-PMMtbZfHoKFjS53dsihg0Mn4-xfYVT2L9VBiLgWQuec7YAQ5GbE991LR2gBWUYeLdHGtuvgMTWWkDA9p_NlDAVjUfHlG9j19XUDWaYSyumpE9zGlnb2hKewIhZxPOpRWuZRaJ93vCV9SziCb4WeLwb54wB4svAU1r2VGdxdsPuRuQvBScfQ8kQHI0MkWElp3PIPL79sDJxA4zwvX07WXM9_lCOXGpt_lhl9Bqh0V0FHMird1TZzNd8itXLi2AiRTyiyo2KaCLQwGRJju8zXbFn-HsHtzB-FvuNPHQFHdHG7if6qRiD-TXKFqPouGQHVZCiyPOCIiUPUWfpIJ5C5VrqkkTAEiqNDXGuSvHmwtjbhEtQlR1Q5Tzn9luT94sGrrmg6COnhVRlUondbqvqRS8_OdPefQPPPej_x67BHA7NNxXyrkT157ykDgm_xL4SdomM1MtTcg0Rer1QfqdiHzZ3FSvD4RoRx1NKfzEqZM2W_JxdnK058qoyMuJ34YihvE8wdORS17AznpDvNkb-ofoo3rqTMfyE0kuc0sEiLLknPjkW_k9kXbvrxMM7CDcCu6VkG697PkGB-fzdfxumZ0QN0omP1gO1aBrV3GtdN91hbL8dGyNBw3M16b1lmkh_2Hm_ezC4odU2aU0Rgat7hhVZCcTRg0du-01PmnJG36uA_NhM_3qcWAOnXd9LR2KuwvjI4Yh-CwnrvgXJb2amYwO_n2MKX9ANhZYzglM3Wa0UpTJ7ke5-Ys901cPHhhOf6WZpp70AjrLwPpJDYw5SikFvVG2SBT39hVSn0bCINOiu-RIQJ0KBgA-BpqD_OVaB648tPtVbHOPVm0D-pGVWl9PAylu9_MT0WCOPaAxyZ_83qwe-EXHX6XsYDhvL-ldb2qPKJaaOZ2nntOzciGjzWhqeNDeqAyt8nIkrnjJNM48Cn0lIU28GTsK9Xr4UNNSruQafXVUrZOD1v7FHJEtVYpOnQDGY1hPtTA1x-ScHFArV6y9WlLN0s_sR3KCMXilPsWFyRkO4sUic2Ly2rKJ_8LKV-urlW9K1-1OyVHI6vKjlpBNpEH1eT9n1L4Ktwcn8xGwu02y6uqHZeQaXEjG7IJBHAThdEySSV86zijyoida3yFU-atWJE3w0eiiuW94xvQgNfYiTtqmXU8b7vcf9uyvqmIupr0nMM0ISb-Z0uQxjWUzsE9xjvo6niUQS56ToVDh1RHL31MkZi4UT1VmfNWCKwAbhe989C-wcNoOj7kBh5AUx6z8_baCGUl1k7IZwY_TG35SyOcwoYD7X6tgzMzfh3vr3GJ4ZGaofXIVGHN-tg-hj6h-4vOBX0LYhEmu6K82mj25X43Dcp-kN8JOKP4BZAJQu9EvBS8ED-Kzxm_IqDc-gdZ2GM1qtUIyIUmPZSIcfGztm69wkJ2wmw5_j_InA1CWWSglOPyxJZezRwEH5uShisIYtLHYc3k_f6FK2SyPDGnqH99AEmVv-QsALLuYY0PbgRvGc3oAMCC5sfMwWU4Zu55ENM7VYEkH2Xym2V1Z2rNAhaxqenDVkrbsZc72nm3rGvmQxi2DLdWzuyCmfT7Qg3v07q0_QqdU7S9UtUEFsBCi61i_mceNl_Ls4pi9sQqaU5c0jF5PWyW-4vKhf6OV0JAau2sD03hDDJKOtxZWRELTqUaQZjOPR-M1EmGcN88oJgVBvzZ-DRUVssWuAMvOJ_-H9s_5MdB3p4YKgWKEl3GEmsRuNfaOAs6NNQpV9MtNm-uPUROJ-xBfd4MV6CJVMt9duGMMRtaNqIueNz8Z0WyuubjFT1CdisHUCSODjIZuoqiid8hEDo6e_VaEskTzxwZc17c2ZrXptkiKpw8LtWGUOcIaE3Dcp48y6tc8R6aTA1zFygT2L-P91JwKJBc_YdRNAm1Ts1on92p1xi_7AG_ZhFJUPWjpluGAni5Y9wwCKVUvY0NGNBUMYtLsn0PpMFCnIPqS4Yq5SLfiSXUjWikDa_ek3kloFEbk8zF2tKNr4MXR78XdDPluBvFNR8NjhhxkaWgCmA0BTS9TqP9xlDAChwwWJJqpCoNWLad3RA6SHHnkkarLPjheVC4BVLGX1otEKVp5igEMGOGMoamEtkzuIaTvddEXXt2u2r0_mlzlxbOXIETB-NEy376Q1Akh8XWPcEB0X7V9BDPlJmd1aYUAVNF1AdqXOmFbLkqBF63C6De1WuPOiRblj5nGSSk6bsPIvm-PhTupzsJcBFrCVCHJbQvqZb7gS-crJqnmf88mBj8iPgUN-c-j8x4srV0tCvwV-tKtu3wgWzblnVrEvWgSMw0CLtHBbm_b9HBpWLmK12SVodiwyGskYYzX9f69KZRHizhWgaiaPJW4OHsZOuHUd1pqxDEeVa88JX0Mj8LhCTYBo4Pgf5zBDuW6RDB9c-ZamJRo0ObSyakzhC0bfQcrpv","DataProtected":true} \ No newline at end of file diff --git a/src/Services/Identity/src/Identity/Data/Configurations/PersistMessageConfiguration.cs b/src/Services/Identity/src/Identity/Data/Configurations/PersistMessageConfiguration.cs deleted file mode 100644 index 843d725..0000000 --- a/src/Services/Identity/src/Identity/Data/Configurations/PersistMessageConfiguration.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using BuildingBlocks.MessageProcessor; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Identity.Data.Configurations; - -public class PersistMessageConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("PersistMessages", IdentityContext.DefaultSchema); - - builder.HasKey(x => x.Id); - - builder.Property(x => x.Id) - .IsRequired(); - - builder.Property(x => x.DeliveryType) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageDeliveryType)Enum.Parse(typeof(MessageDeliveryType), v)) - .IsRequired() - .IsUnicode(false); - - builder.Property(x => x.DeliveryType) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageDeliveryType)Enum.Parse(typeof(MessageDeliveryType), v)) - .IsRequired() - .IsUnicode(false); - - builder.Property(x => x.MessageStatus) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageStatus)Enum.Parse(typeof(MessageStatus), v)) - .IsRequired() - .IsUnicode(false); - } -} diff --git a/src/Services/Identity/src/Identity/Data/IdentityDataSeeder.cs b/src/Services/Identity/src/Identity/Data/IdentityDataSeeder.cs index d6556f4..85c1e35 100644 --- a/src/Services/Identity/src/Identity/Data/IdentityDataSeeder.cs +++ b/src/Services/Identity/src/Identity/Data/IdentityDataSeeder.cs @@ -1,5 +1,7 @@ using System; using System.Threading.Tasks; +using BuildingBlocks.Contracts.EventBus.Messages; +using BuildingBlocks.Core; using BuildingBlocks.EFCore; using Identity.Identity.Constants; using Identity.Identity.Models; @@ -10,12 +12,16 @@ namespace Identity.Data; public class IdentityDataSeeder : IDataSeeder { private readonly RoleManager> _roleManager; + private readonly IEventDispatcher _eventDispatcher; private readonly UserManager _userManager; - public IdentityDataSeeder(UserManager userManager, RoleManager> roleManager) + public IdentityDataSeeder(UserManager userManager, + RoleManager> roleManager, + IEventDispatcher eventDispatcher) { _userManager = userManager; _roleManager = roleManager; + _eventDispatcher = eventDispatcher; } public async Task SeedAllAsync() @@ -42,6 +48,7 @@ public class IdentityDataSeeder : IDataSeeder FirstName = "Sam", LastName = "H", UserName = "samh", + PassPortNumber = "123456789", Email = "sam@test.com", SecurityStamp = Guid.NewGuid().ToString() }; @@ -49,16 +56,21 @@ public class IdentityDataSeeder : IDataSeeder var result = await _userManager.CreateAsync(user, "Admin@123456"); if (result.Succeeded) + { await _userManager.AddToRoleAsync(user, Constants.Role.Admin); + + await _eventDispatcher.SendAsync(new UserCreated(user.Id, user.FirstName + " " + user.LastName, user.PassPortNumber)); + } } if (await _userManager.FindByNameAsync("meysamh2") == null) { var user = new ApplicationUser { - FirstName = "Sam", - LastName = "H", + FirstName = "Sam2", + LastName = "H2", UserName = "samh2", + PassPortNumber = "987654321", Email = "sam2@test.com", SecurityStamp = Guid.NewGuid().ToString() }; @@ -66,7 +78,11 @@ public class IdentityDataSeeder : IDataSeeder var result = await _userManager.CreateAsync(user, "User@123456"); if (result.Succeeded) + { await _userManager.AddToRoleAsync(user, Constants.Role.User); + + await _eventDispatcher.SendAsync(new UserCreated(user.Id, user.FirstName + " " + user.LastName, user.PassPortNumber)); + } } } } diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220418181648_Initial.Designer.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220418181648_Initial.Designer.cs deleted file mode 100644 index d535aa1..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220418181648_Initial.Designer.cs +++ /dev/null @@ -1,328 +0,0 @@ -// -using System; -using Identity.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Identity.Data.Migrations -{ - [DbContext(typeof(IdentityContext))] - [Migration("20220418181648_Initial")] - partial class Initial - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BuildingBlocks.Outbox.OutboxMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CorrelationId") - .HasColumnType("uniqueidentifier"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OccurredOn") - .HasColumnType("datetime2"); - - b.Property("ProcessedOn") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OutboxMessages", (string)null); - }); - - modelBuilder.Entity("Identity.Identity.Models.ApplicationUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PassPortNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.Designer.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.Designer.cs deleted file mode 100644 index ce3c7bc..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.Designer.cs +++ /dev/null @@ -1,360 +0,0 @@ -// -using System; -using Identity.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Identity.Data.Migrations -{ - [DbContext(typeof(IdentityContext))] - [Migration("20220421202152_Add-Internal-Messages")] - partial class AddInternalMessages - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BuildingBlocks.InternalProcessor.InternalMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CommandType") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CorrelationId") - .HasColumnType("uniqueidentifier"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OccurredOn") - .HasColumnType("datetime2"); - - b.Property("ProcessedOn") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.ToTable("InternalMessages", (string)null); - }); - - modelBuilder.Entity("BuildingBlocks.Outbox.OutboxMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CorrelationId") - .HasColumnType("uniqueidentifier"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OccurredOn") - .HasColumnType("datetime2"); - - b.Property("ProcessedOn") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("OutboxMessages", (string)null); - }); - - modelBuilder.Entity("Identity.Identity.Models.ApplicationUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PassPortNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.cs deleted file mode 100644 index a156e10..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220421202152_Add-Internal-Messages.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Identity.Data.Migrations -{ - public partial class AddInternalMessages : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "InternalMessages", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - OccurredOn = table.Column(type: "datetime2", nullable: false), - CommandType = table.Column(type: "nvarchar(max)", nullable: false), - Data = table.Column(type: "nvarchar(max)", nullable: false), - ProcessedOn = table.Column(type: "datetime2", nullable: true), - CorrelationId = table.Column(type: "uniqueidentifier", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_InternalMessages", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "InternalMessages"); - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.Designer.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.Designer.cs deleted file mode 100644 index 66d16f8..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.Designer.cs +++ /dev/null @@ -1,360 +0,0 @@ -// -using System; -using Identity.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Identity.Data.Migrations -{ - [DbContext(typeof(IdentityContext))] - [Migration("20220422121534_Update-EventId")] - partial class UpdateEventId - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BuildingBlocks.InternalProcessor.InternalMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CommandType") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CorrelationId") - .HasColumnType("uniqueidentifier"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OccurredOn") - .HasColumnType("datetime2"); - - b.Property("ProcessedOn") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.ToTable("InternalMessages", (string)null); - }); - - modelBuilder.Entity("BuildingBlocks.Outbox.OutboxMessage", b => - { - b.Property("EventId") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CorrelationId") - .HasColumnType("uniqueidentifier"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OccurredOn") - .HasColumnType("datetime2"); - - b.Property("ProcessedOn") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("EventId"); - - b.ToTable("OutboxMessages", (string)null); - }); - - modelBuilder.Entity("Identity.Identity.Models.ApplicationUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PassPortNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.cs deleted file mode 100644 index 45cd9de..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220422121534_Update-EventId.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Identity.Data.Migrations -{ - public partial class UpdateEventId : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "Id", - table: "OutboxMessages", - newName: "EventId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "EventId", - table: "OutboxMessages", - newName: "Id"); - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.Designer.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.Designer.cs deleted file mode 100644 index 130976b..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.Designer.cs +++ /dev/null @@ -1,360 +0,0 @@ -// -using System; -using Identity.Data; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Identity.Data.Migrations -{ - [DbContext(typeof(IdentityContext))] - [Migration("20220422121846_Update-Internal-EventId")] - partial class UpdateInternalEventId - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "6.0.1") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - - modelBuilder.Entity("BuildingBlocks.InternalProcessor.InternalMessage", b => - { - b.Property("EventId") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CommandType") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("CorrelationId") - .HasColumnType("uniqueidentifier"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OccurredOn") - .HasColumnType("datetime2"); - - b.Property("ProcessedOn") - .HasColumnType("datetime2"); - - b.HasKey("EventId"); - - b.ToTable("InternalMessages", (string)null); - }); - - modelBuilder.Entity("BuildingBlocks.Outbox.OutboxMessage", b => - { - b.Property("EventId") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("CorrelationId") - .HasColumnType("uniqueidentifier"); - - b.Property("Data") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EventType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OccurredOn") - .HasColumnType("datetime2"); - - b.Property("ProcessedOn") - .HasColumnType("datetime2"); - - b.Property("Type") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("EventId"); - - b.ToTable("OutboxMessages", (string)null); - }); - - modelBuilder.Entity("Identity.Identity.Models.ApplicationUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("AccessFailedCount") - .HasColumnType("int"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Email") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("EmailConfirmed") - .HasColumnType("bit"); - - b.Property("FirstName") - .HasColumnType("nvarchar(max)"); - - b.Property("LastName") - .HasColumnType("nvarchar(max)"); - - b.Property("LockoutEnabled") - .HasColumnType("bit"); - - b.Property("LockoutEnd") - .HasColumnType("datetimeoffset"); - - b.Property("NormalizedEmail") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedUserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("PassPortNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PasswordHash") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumber") - .HasColumnType("nvarchar(max)"); - - b.Property("PhoneNumberConfirmed") - .HasColumnType("bit"); - - b.Property("SecurityStamp") - .HasColumnType("nvarchar(max)"); - - b.Property("TwoFactorEnabled") - .HasColumnType("bit"); - - b.Property("UserName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasDatabaseName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasDatabaseName("UserNameIndex") - .HasFilter("[NormalizedUserName] IS NOT NULL"); - - b.ToTable("AspNetUsers", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("bigint"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken() - .HasColumnType("nvarchar(max)"); - - b.Property("Name") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.Property("NormalizedName") - .HasMaxLength(256) - .HasColumnType("nvarchar(256)"); - - b.HasKey("Id"); - - b.HasIndex("NormalizedName") - .IsUnique() - .HasDatabaseName("RoleNameIndex") - .HasFilter("[NormalizedName] IS NOT NULL"); - - b.ToTable("AspNetRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetRoleClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); - - b.Property("ClaimType") - .HasColumnType("nvarchar(max)"); - - b.Property("ClaimValue") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserClaims", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderKey") - .HasColumnType("nvarchar(450)"); - - b.Property("ProviderDisplayName") - .HasColumnType("nvarchar(max)"); - - b.Property("UserId") - .HasColumnType("bigint"); - - b.HasKey("LoginProvider", "ProviderKey"); - - b.HasIndex("UserId"); - - b.ToTable("AspNetUserLogins", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("RoleId") - .HasColumnType("bigint"); - - b.HasKey("UserId", "RoleId"); - - b.HasIndex("RoleId"); - - b.ToTable("AspNetUserRoles", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.Property("UserId") - .HasColumnType("bigint"); - - b.Property("LoginProvider") - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .HasColumnType("nvarchar(450)"); - - b.Property("Value") - .HasColumnType("nvarchar(max)"); - - b.HasKey("UserId", "LoginProvider", "Name"); - - b.ToTable("AspNetUserTokens", (string)null); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => - { - b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) - .WithMany() - .HasForeignKey("RoleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => - { - b.HasOne("Identity.Identity.Models.ApplicationUser", null) - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.cs deleted file mode 100644 index 6539a06..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220422121846_Update-Internal-EventId.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Identity.Data.Migrations -{ - public partial class UpdateInternalEventId : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "Id", - table: "InternalMessages", - newName: "EventId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "EventId", - table: "InternalMessages", - newName: "Id"); - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220616123336_Add-PersistMessages.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220616123336_Add-PersistMessages.cs deleted file mode 100644 index 576e0ff..0000000 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220616123336_Add-PersistMessages.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Identity.Data.Migrations -{ - public partial class AddPersistMessages : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "InternalMessages"); - - migrationBuilder.DropTable( - name: "OutboxMessages"); - - migrationBuilder.EnsureSchema( - name: "dbo"); - - migrationBuilder.CreateTable( - name: "PersistMessages", - schema: "dbo", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - DataType = table.Column(type: "nvarchar(max)", nullable: true), - Data = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - RetryCount = table.Column(type: "int", nullable: false), - MessageStatus = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false), - DeliveryType = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistMessages", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "PersistMessages", - schema: "dbo"); - - migrationBuilder.CreateTable( - name: "InternalMessages", - columns: table => new - { - EventId = table.Column(type: "uniqueidentifier", nullable: false), - CommandType = table.Column(type: "nvarchar(max)", nullable: false), - CorrelationId = table.Column(type: "uniqueidentifier", nullable: true), - Data = table.Column(type: "nvarchar(max)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - OccurredOn = table.Column(type: "datetime2", nullable: false), - ProcessedOn = table.Column(type: "datetime2", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_InternalMessages", x => x.EventId); - }); - - migrationBuilder.CreateTable( - name: "OutboxMessages", - columns: table => new - { - EventId = table.Column(type: "uniqueidentifier", nullable: false), - CorrelationId = table.Column(type: "uniqueidentifier", nullable: true), - Data = table.Column(type: "nvarchar(max)", nullable: false), - EventType = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - OccurredOn = table.Column(type: "datetime2", nullable: false), - ProcessedOn = table.Column(type: "datetime2", nullable: true), - Type = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_OutboxMessages", x => x.EventId); - }); - } - } -} diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220616123336_Add-PersistMessages.Designer.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220728175937_initial.Designer.cs similarity index 88% rename from src/Services/Identity/src/Identity/Data/Migrations/20220616123336_Add-PersistMessages.Designer.cs rename to src/Services/Identity/src/Identity/Data/Migrations/20220728175937_initial.Designer.cs index 6f7313f..a511463 100644 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220616123336_Add-PersistMessages.Designer.cs +++ b/src/Services/Identity/src/Identity/Data/Migrations/20220728175937_initial.Designer.cs @@ -12,8 +12,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Identity.Data.Migrations { [DbContext(typeof(IdentityContext))] - [Migration("20220616123336_Add-PersistMessages")] - partial class AddPersistMessages + [Migration("20220728175937_initial")] + partial class initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) { @@ -24,41 +24,6 @@ namespace Identity.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .HasColumnType("nvarchar(max)"); - - b.Property("DataType") - .HasColumnType("nvarchar(max)"); - - b.Property("DeliveryType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("MessageStatus") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("RetryCount") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("PersistMessages", "dbo"); - }); - modelBuilder.Entity("Identity.Identity.Models.ApplicationUser", b => { b.Property("Id") diff --git a/src/Services/Identity/src/Identity/Data/Migrations/20220418181648_Initial.cs b/src/Services/Identity/src/Identity/Data/Migrations/20220728175937_initial.cs similarity index 89% rename from src/Services/Identity/src/Identity/Data/Migrations/20220418181648_Initial.cs rename to src/Services/Identity/src/Identity/Data/Migrations/20220728175937_initial.cs index 70abdd1..a056fed 100644 --- a/src/Services/Identity/src/Identity/Data/Migrations/20220418181648_Initial.cs +++ b/src/Services/Identity/src/Identity/Data/Migrations/20220728175937_initial.cs @@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore.Migrations; namespace Identity.Data.Migrations { - public partial class Initial : Migration + public partial class initial : Migration { protected override void Up(MigrationBuilder migrationBuilder) { @@ -53,24 +53,6 @@ namespace Identity.Data.Migrations table.PrimaryKey("PK_AspNetUsers", x => x.Id); }); - migrationBuilder.CreateTable( - name: "OutboxMessages", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - OccurredOn = table.Column(type: "datetime2", nullable: false), - Type = table.Column(type: "nvarchar(max)", nullable: false), - Data = table.Column(type: "nvarchar(max)", nullable: false), - ProcessedOn = table.Column(type: "datetime2", nullable: true), - EventType = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false), - CorrelationId = table.Column(type: "uniqueidentifier", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_OutboxMessages", x => x.Id); - }); - migrationBuilder.CreateTable( name: "AspNetRoleClaims", columns: table => new @@ -234,9 +216,6 @@ namespace Identity.Data.Migrations migrationBuilder.DropTable( name: "AspNetUserTokens"); - migrationBuilder.DropTable( - name: "OutboxMessages"); - migrationBuilder.DropTable( name: "AspNetRoles"); diff --git a/src/Services/Identity/src/Identity/Data/Migrations/IdentityContextModelSnapshot.cs b/src/Services/Identity/src/Identity/Data/Migrations/IdentityContextModelSnapshot.cs index 862f04d..29e7d27 100644 --- a/src/Services/Identity/src/Identity/Data/Migrations/IdentityContextModelSnapshot.cs +++ b/src/Services/Identity/src/Identity/Data/Migrations/IdentityContextModelSnapshot.cs @@ -22,41 +22,6 @@ namespace Identity.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .HasColumnType("nvarchar(max)"); - - b.Property("DataType") - .HasColumnType("nvarchar(max)"); - - b.Property("DeliveryType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("MessageStatus") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("RetryCount") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("PersistMessages", "dbo"); - }); - modelBuilder.Entity("Identity.Identity.Models.ApplicationUser", b => { b.Property("Id") diff --git a/src/Services/Identity/src/Identity/EventMapper.cs b/src/Services/Identity/src/Identity/EventMapper.cs index f4d593a..d7859dc 100644 --- a/src/Services/Identity/src/Identity/EventMapper.cs +++ b/src/Services/Identity/src/Identity/EventMapper.cs @@ -13,7 +13,7 @@ public sealed class EventMapper : IEventMapper }; } - public InternalCommand MapToInternalCommand(IDomainEvent @event) + public IInternalCommand MapToInternalCommand(IDomainEvent @event) { return @event switch { diff --git a/src/Services/Identity/src/Identity/Extensions/CoreExtensions.cs b/src/Services/Identity/src/Identity/Extensions/CoreExtensions.cs new file mode 100644 index 0000000..5fa0526 --- /dev/null +++ b/src/Services/Identity/src/Identity/Extensions/CoreExtensions.cs @@ -0,0 +1,15 @@ +using BuildingBlocks.Core; +using Microsoft.Extensions.DependencyInjection; + +namespace Identity.Extensions; + +public static class CoreExtensions +{ + public static IServiceCollection AddCore(this IServiceCollection services) + { + services.AddTransient(); + services.AddScoped(); + + return services; + } +} diff --git a/src/Services/Identity/src/Identity/Extensions/MediatRExtensions.cs b/src/Services/Identity/src/Identity/Extensions/MediatRExtensions.cs index 0d13166..9b0043d 100644 --- a/src/Services/Identity/src/Identity/Extensions/MediatRExtensions.cs +++ b/src/Services/Identity/src/Identity/Extensions/MediatRExtensions.cs @@ -13,7 +13,6 @@ public static class MediatRExtensions services.AddMediatR(typeof(IdentityRoot).Assembly); services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); - services.AddScoped(typeof(IPipelineBehavior<,>), typeof(EfTxBehavior<,>)); return services; } diff --git a/src/Services/Identity/src/Identity/Identity.csproj b/src/Services/Identity/src/Identity/Identity.csproj index 74cbbc4..843ad48 100644 --- a/src/Services/Identity/src/Identity/Identity.csproj +++ b/src/Services/Identity/src/Identity/Identity.csproj @@ -15,4 +15,9 @@ + + + + + diff --git a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/RegisterNewUserCommandHandler.cs b/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/RegisterNewUserCommandHandler.cs index 2a35c2b..4f3c722 100644 --- a/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/RegisterNewUserCommandHandler.cs +++ b/src/Services/Identity/src/Identity/Identity/Features/RegisterNewUser/RegisterNewUserCommandHandler.cs @@ -5,6 +5,7 @@ using Ardalis.GuardClauses; using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.Core; using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using Identity.Identity.Dtos; using Identity.Identity.Exceptions; using Identity.Identity.Models; @@ -50,7 +51,7 @@ public class RegisterNewUserCommandHandler : ICommandHandler e.Description))); await _eventDispatcher.SendAsync(new UserCreated(applicationUser.Id, applicationUser.FirstName + " " + applicationUser.LastName, - applicationUser.PassPortNumber), cancellationToken: cancellationToken); + applicationUser.PassPortNumber),cancellationToken: cancellationToken); return new RegisterNewUserResponseDto { diff --git a/src/Services/Identity/src/Identity/IdentityRoot.cs b/src/Services/Identity/src/Identity/IdentityRoot.cs index 063c16b..05b7694 100644 --- a/src/Services/Identity/src/Identity/IdentityRoot.cs +++ b/src/Services/Identity/src/Identity/IdentityRoot.cs @@ -2,5 +2,4 @@ namespace Identity; public class IdentityRoot { - -} \ No newline at end of file +} diff --git a/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs b/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs index 111e34d..12ac69d 100644 --- a/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs +++ b/src/Services/Identity/tests/IntegrationTest/Fakes/FakeRegisterNewUserCommand.cs @@ -7,6 +7,7 @@ public class FakeRegisterNewUserCommand : AutoFaker { public FakeRegisterNewUserCommand() { + RuleFor(r => r.Username, _ => "TestUser"); RuleFor(r => r.Password, _ => "Password@123"); RuleFor(r => r.ConfirmPassword, _ => "Password@123"); RuleFor(r => r.Email, _ => "test@test.com"); diff --git a/src/Services/Passenger/src/Passenger.Api/Program.cs b/src/Services/Passenger/src/Passenger.Api/Program.cs index d13fb8a..95eb0bb 100644 --- a/src/Services/Passenger/src/Passenger.Api/Program.cs +++ b/src/Services/Passenger/src/Passenger.Api/Program.cs @@ -7,8 +7,9 @@ using BuildingBlocks.Jwt; using BuildingBlocks.Logging; using BuildingBlocks.Mapster; using BuildingBlocks.MassTransit; -using BuildingBlocks.MessageProcessor; +using BuildingBlocks.Mongo; using BuildingBlocks.OpenTelemetry; +using BuildingBlocks.PersistMessageProcessor; using BuildingBlocks.Swagger; using BuildingBlocks.Web; using Figgle; @@ -29,9 +30,11 @@ var appOptions = builder.Services.GetOptions("AppOptions"); Console.WriteLine(FiggleFonts.Standard.Render(appOptions.Name)); builder.Services.AddCustomDbContext(configuration); +builder.Services.AddMongoDbContext(configuration); builder.Services.AddPersistMessage(configuration); builder.AddCustomSerilog(); +builder.Services.AddCore(); builder.Services.AddJwt(); builder.Services.AddControllers(); builder.Services.AddCustomSwagger(configuration, typeof(PassengerRoot).Assembly); @@ -41,7 +44,6 @@ builder.Services.AddValidatorsFromAssembly(typeof(PassengerRoot).Assembly); builder.Services.AddCustomProblemDetails(); builder.Services.AddCustomMapster(typeof(PassengerRoot).Assembly); builder.Services.AddHttpContextAccessor(); -builder.Services.AddTransient(); builder.Services.AddCustomHealthCheck(); builder.Services.AddCustomMassTransit(typeof(PassengerRoot).Assembly, env); builder.Services.AddCustomOpenTelemetry(); diff --git a/src/Services/Passenger/src/Passenger.Api/appsettings.json b/src/Services/Passenger/src/Passenger.Api/appsettings.json index ff5f1f2..84afe9f 100644 --- a/src/Services/Passenger/src/Passenger.Api/appsettings.json +++ b/src/Services/Passenger/src/Passenger.Api/appsettings.json @@ -5,6 +5,10 @@ "ConnectionStrings": { "DefaultConnection": "Server=.\\sqlexpress;Database=PassengerDB;Trusted_Connection=True;MultipleActiveResultSets=true" }, + "MongoOptions": { + "ConnectionString": "mongodb://localhost:27017", + "DatabaseName": "passenger-db" + }, "Jwt": { "Authority": "https://localhost:5005", "Audience": "passenger-api" @@ -22,7 +26,8 @@ }, "PersistMessageOptions": { "Interval": 30, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageDB;Trusted_Connection=True;MultipleActiveResultSets=true" }, "AllowedHosts": "*" } diff --git a/src/Services/Passenger/src/Passenger.Api/appsettings.test.json b/src/Services/Passenger/src/Passenger.Api/appsettings.test.json index 69307e9..266dad5 100644 --- a/src/Services/Passenger/src/Passenger.Api/appsettings.test.json +++ b/src/Services/Passenger/src/Passenger.Api/appsettings.test.json @@ -18,6 +18,7 @@ }, "PersistMessageOptions": { "Interval": 1, - "Enabled": true + "Enabled": true, + "ConnectionString": "Server=.\\sqlexpress;Database=PersistMessageTestDB;Trusted_Connection=True;MultipleActiveResultSets=true" } } diff --git a/src/Services/Passenger/src/Passenger/Data/Configurations/PersistMessageConfiguration.cs b/src/Services/Passenger/src/Passenger/Data/Configurations/PersistMessageConfiguration.cs deleted file mode 100644 index a711b6a..0000000 --- a/src/Services/Passenger/src/Passenger/Data/Configurations/PersistMessageConfiguration.cs +++ /dev/null @@ -1,42 +0,0 @@ -using BuildingBlocks.MessageProcessor; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; - -namespace Passenger.Data.Configurations; - -public class PersistMessageConfiguration : IEntityTypeConfiguration -{ - public void Configure(EntityTypeBuilder builder) - { - builder.ToTable("PersistMessages", PassengerDbContext.DefaultSchema); - - builder.HasKey(x => x.Id); - - builder.Property(x => x.Id) - .IsRequired(); - - builder.Property(x => x.DeliveryType) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageDeliveryType)Enum.Parse(typeof(MessageDeliveryType), v)) - .IsRequired() - .IsUnicode(false); - - builder.Property(x => x.DeliveryType) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageDeliveryType)Enum.Parse(typeof(MessageDeliveryType), v)) - .IsRequired() - .IsUnicode(false); - - builder.Property(x => x.MessageStatus) - .HasMaxLength(50) - .HasConversion( - v => v.ToString(), - v => (MessageStatus)Enum.Parse(typeof(MessageStatus), v)) - .IsRequired() - .IsUnicode(false); - } -} diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.cs b/src/Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.cs deleted file mode 100644 index faae54a..0000000 --- a/src/Services/Passenger/src/Passenger/Data/Migrations/20220616122705_Add-PersistMessages.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Passenger.Data.Migrations -{ - public partial class AddPersistMessages : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "PersistMessages", - schema: "dbo", - columns: table => new - { - Id = table.Column(type: "uniqueidentifier", nullable: false), - DataType = table.Column(type: "nvarchar(max)", nullable: true), - Data = table.Column(type: "nvarchar(max)", nullable: true), - Created = table.Column(type: "datetime2", nullable: false), - RetryCount = table.Column(type: "int", nullable: false), - MessageStatus = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false), - DeliveryType = table.Column(type: "varchar(50)", unicode: false, maxLength: 50, nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PersistMessages", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "PersistMessages", - schema: "dbo"); - } - } -} diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/20220523195643_initial.Designer.cs b/src/Services/Passenger/src/Passenger/Data/Migrations/20220728180020_initial.Designer.cs similarity index 98% rename from src/Services/Passenger/src/Passenger/Data/Migrations/20220523195643_initial.Designer.cs rename to src/Services/Passenger/src/Passenger/Data/Migrations/20220728180020_initial.Designer.cs index 9e7744e..aa6b184 100644 --- a/src/Services/Passenger/src/Passenger/Data/Migrations/20220523195643_initial.Designer.cs +++ b/src/Services/Passenger/src/Passenger/Data/Migrations/20220728180020_initial.Designer.cs @@ -12,7 +12,7 @@ using Passenger.Data; namespace Passenger.Data.Migrations { [DbContext(typeof(PassengerDbContext))] - [Migration("20220523195643_initial")] + [Migration("20220728180020_initial")] partial class initial { protected override void BuildTargetModel(ModelBuilder modelBuilder) diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/20220523195643_initial.cs b/src/Services/Passenger/src/Passenger/Data/Migrations/20220728180020_initial.cs similarity index 100% rename from src/Services/Passenger/src/Passenger/Data/Migrations/20220523195643_initial.cs rename to src/Services/Passenger/src/Passenger/Data/Migrations/20220728180020_initial.cs diff --git a/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs b/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs index 3687087..df21933 100644 --- a/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs +++ b/src/Services/Passenger/src/Passenger/Data/Migrations/PassengerDbContextModelSnapshot.cs @@ -22,41 +22,6 @@ namespace Passenger.Data.Migrations SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); - modelBuilder.Entity("BuildingBlocks.MessageProcessor.PersistMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uniqueidentifier"); - - b.Property("Created") - .HasColumnType("datetime2"); - - b.Property("Data") - .HasColumnType("nvarchar(max)"); - - b.Property("DataType") - .HasColumnType("nvarchar(max)"); - - b.Property("DeliveryType") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("MessageStatus") - .IsRequired() - .HasMaxLength(50) - .IsUnicode(false) - .HasColumnType("varchar(50)"); - - b.Property("RetryCount") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("PersistMessages", "dbo"); - }); - modelBuilder.Entity("Passenger.Passengers.Models.Passenger", b => { b.Property("Id") diff --git a/src/Services/Passenger/src/Passenger/Data/PassengerDbContext.cs b/src/Services/Passenger/src/Passenger/Data/PassengerDbContext.cs index f2c48ea..7a80a04 100644 --- a/src/Services/Passenger/src/Passenger/Data/PassengerDbContext.cs +++ b/src/Services/Passenger/src/Passenger/Data/PassengerDbContext.cs @@ -1,5 +1,6 @@ using System.Reflection; using BuildingBlocks.EFCore; +using BuildingBlocks.Utils; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; @@ -9,7 +10,7 @@ public sealed class PassengerDbContext : AppDbContextBase { public const string DefaultSchema = "dbo"; - public PassengerDbContext(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base(options, httpContextAccessor) + public PassengerDbContext(DbContextOptions options, ICurrentUserProvider currentUserProvider) : base(options, currentUserProvider) { } diff --git a/src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs b/src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs new file mode 100644 index 0000000..6991084 --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Data/PassengerReadDbContext.cs @@ -0,0 +1,17 @@ +using BuildingBlocks.Mongo; +using Humanizer; +using Microsoft.Extensions.Options; +using MongoDB.Driver; +using Passenger.Passengers.Models.Reads; + +namespace Passenger.Data; + +public class PassengerReadDbContext : MongoDbContext +{ + public PassengerReadDbContext(IOptions options) : base(options) + { + Passenger = GetCollection(nameof(Passenger).Underscore()); + } + + public IMongoCollection Passenger { get; } +} diff --git a/src/Services/Passenger/src/Passenger/EventMapper.cs b/src/Services/Passenger/src/Passenger/EventMapper.cs index 13a9f30..7a2be7e 100644 --- a/src/Services/Passenger/src/Passenger/EventMapper.cs +++ b/src/Services/Passenger/src/Passenger/EventMapper.cs @@ -1,5 +1,10 @@ +using BuildingBlocks.Contracts.EventBus.Messages; using BuildingBlocks.Core; using BuildingBlocks.Core.Event; +using Passenger.Passengers.Events.Domain; +using Passenger.Passengers.Features.CompleteRegisterPassenger.Reads; +using Passenger.Passengers.Models; +using PassengerType = BuildingBlocks.Contracts.Grpc.PassengerType; namespace Passenger; @@ -9,14 +14,20 @@ public sealed class EventMapper : IEventMapper { return @event switch { + PassengerRegistrationCompletedDomainEvent e => new PassengerRegistrationCompleted(e.Id), + PassengerCreatedDomainEvent e => new PassengerCreated(e.Id), _ => null }; } - public InternalCommand MapToInternalCommand(IDomainEvent @event) + public IInternalCommand MapToInternalCommand(IDomainEvent @event) { return @event switch { + PassengerRegistrationCompletedDomainEvent e => new CompleteRegisterPassengerMongoCommand(e.Id, e.PassportNumber, e.Name, e.PassengerType, + e.Age, e.IsDeleted), + PassengerCreatedDomainEvent e => new CompleteRegisterPassengerMongoCommand(e.Id, e.PassportNumber, e.Name, Passengers.Models.PassengerType.Unknown, + 0, e.IsDeleted), _ => null }; } diff --git a/src/Services/Passenger/src/Passenger/Extensions/CoreExtensions.cs b/src/Services/Passenger/src/Passenger/Extensions/CoreExtensions.cs new file mode 100644 index 0000000..d6e756d --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Extensions/CoreExtensions.cs @@ -0,0 +1,17 @@ +using BuildingBlocks.Core; +using BuildingBlocks.Utils; +using Microsoft.Extensions.DependencyInjection; + +namespace Passenger.Extensions; + +public static class CoreExtensions +{ + public static IServiceCollection AddCore(this IServiceCollection services) + { + services.AddScoped(); + services.AddTransient(); + services.AddScoped(); + + return services; + } +} diff --git a/src/Services/Passenger/src/Passenger/Identity/RegisterNewUser/RegisterNewUserConsumerHandler.cs b/src/Services/Passenger/src/Passenger/Identity/RegisterNewUser/RegisterNewUserConsumerHandler.cs index 80107f7..b9c519d 100644 --- a/src/Services/Passenger/src/Passenger/Identity/RegisterNewUser/RegisterNewUserConsumerHandler.cs +++ b/src/Services/Passenger/src/Passenger/Identity/RegisterNewUser/RegisterNewUserConsumerHandler.cs @@ -1,28 +1,45 @@ using Ardalis.GuardClauses; using BuildingBlocks.Contracts.EventBus.Messages; +using BuildingBlocks.Core; +using BuildingBlocks.Core.Event; using BuildingBlocks.IdsGenerator; using MassTransit; +using Microsoft.EntityFrameworkCore; using Passenger.Data; +using Passenger.Passengers.Events.Domain; namespace Passenger.Identity.RegisterNewUser; public class RegisterNewUserConsumerHandler : IConsumer { private readonly PassengerDbContext _passengerDbContext; + private readonly IEventDispatcher _eventDispatcher; - public RegisterNewUserConsumerHandler(PassengerDbContext passengerDbContext) + public RegisterNewUserConsumerHandler(PassengerDbContext passengerDbContext, + IEventDispatcher eventDispatcher) { _passengerDbContext = passengerDbContext; + _eventDispatcher = eventDispatcher; } public async Task Consume(ConsumeContext context) { Guard.Against.Null(context.Message, nameof(UserCreated)); - var passenger = Passengers.Models.Passenger.Create(SnowFlakIdGenerator.NewId(), context.Message.Name, context.Message.PassportNumber); + var passengerExist = await _passengerDbContext.Passengers.AnyAsync(x => x.PassportNumber == context.Message.PassportNumber); + + if (passengerExist) + return; + + var passenger = Passengers.Models.Passenger.Create(SnowFlakIdGenerator.NewId(), context.Message.Name, + context.Message.PassportNumber); await _passengerDbContext.AddAsync(passenger); await _passengerDbContext.SaveChangesAsync(); + + await _eventDispatcher.SendAsync( + new PassengerCreatedDomainEvent(passenger.Id, passenger.Name, passenger.PassportNumber), + typeof(IInternalCommand)); } } diff --git a/src/Services/Passenger/src/Passenger/Passenger.csproj b/src/Services/Passenger/src/Passenger/Passenger.csproj index 487d10d..1cd1e12 100644 --- a/src/Services/Passenger/src/Passenger/Passenger.csproj +++ b/src/Services/Passenger/src/Passenger/Passenger.csproj @@ -14,7 +14,6 @@ - diff --git a/src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerCreatedDomainEvent.cs b/src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerCreatedDomainEvent.cs index 65eddc1..bf501f5 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerCreatedDomainEvent.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerCreatedDomainEvent.cs @@ -1,5 +1,5 @@ -using BuildingBlocks.Core.Event; +using BuildingBlocks.Core.Event; namespace Passenger.Passengers.Events.Domain; -public record PassengerCreatedDomainEvent(string FlightNumber) : IDomainEvent; +public record PassengerCreatedDomainEvent(long Id, string Name, string PassportNumber, bool IsDeleted = false) : IDomainEvent; diff --git a/src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerRegistrationCompletedDomainEvent.cs b/src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerRegistrationCompletedDomainEvent.cs new file mode 100644 index 0000000..f31f80a --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Passengers/Events/Domain/PassengerRegistrationCompletedDomainEvent.cs @@ -0,0 +1,7 @@ +using BuildingBlocks.Core.Event; +using Passenger.Passengers.Models; + +namespace Passenger.Passengers.Events.Domain; + +public record PassengerRegistrationCompletedDomainEvent(long Id, string Name, string PassportNumber, + PassengerType PassengerType, int Age, bool IsDeleted = false) : IDomainEvent; diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/CompleteRegisterPassengerCommand.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/CompleteRegisterPassengerCommand.cs index 79d11c3..33f9ba7 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/CompleteRegisterPassengerCommand.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/CompleteRegisterPassengerCommand.cs @@ -1,11 +1,12 @@ using BuildingBlocks.Core.CQRS; +using BuildingBlocks.Core.Event; using BuildingBlocks.IdsGenerator; using Passenger.Passengers.Dtos; using Passenger.Passengers.Models; namespace Passenger.Passengers.Features.CompleteRegisterPassenger; -public record CompleteRegisterPassengerCommand(string PassportNumber, PassengerType PassengerType, int Age) : ICommand +public record CompleteRegisterPassengerCommand(string PassportNumber, PassengerType PassengerType, int Age) : ICommand, IInternalCommand { public long Id { get; init; } = SnowFlakIdGenerator.NewId(); } diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommand.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommand.cs new file mode 100644 index 0000000..a3f6baa --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommand.cs @@ -0,0 +1,24 @@ +using BuildingBlocks.Core.Event; +using Passenger.Passengers.Models; + +namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Reads; + +public class CompleteRegisterPassengerMongoCommand : InternalCommand +{ + public CompleteRegisterPassengerMongoCommand(long id, string passportNumber, string name, + PassengerType passengerType, int age, bool isDeleted) + { + Id = id; + PassportNumber = passportNumber; + Name = name; + PassengerType = passengerType; + Age = age; + IsDeleted = isDeleted; + } + + public string PassportNumber { get; } + public string Name { get; } + public PassengerType PassengerType { get; } + public int Age { get; } + public bool IsDeleted { get; } +} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommandHandler.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommandHandler.cs new file mode 100644 index 0000000..b6e9f0a --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/CompleteRegisterPassenger/Reads/CompleteRegisterPassengerMongoCommandHandler.cs @@ -0,0 +1,56 @@ +using Ardalis.GuardClauses; +using BuildingBlocks.Contracts.EventBus.Messages; +using BuildingBlocks.Core.CQRS; +using MapsterMapper; +using MediatR; +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using Passenger.Data; +using Passenger.Passengers.Models.Reads; + +namespace Passenger.Passengers.Features.CompleteRegisterPassenger.Reads; + +public class CompleteRegisterPassengerMongoCommandHandler : ICommandHandler +{ + private readonly PassengerReadDbContext _passengerReadDbContext; + private readonly IMapper _mapper; + + public CompleteRegisterPassengerMongoCommandHandler( + PassengerReadDbContext passengerReadDbContext, + IMapper mapper) + { + _passengerReadDbContext = passengerReadDbContext; + _mapper = mapper; + } + + public async Task Handle(CompleteRegisterPassengerMongoCommand command, CancellationToken cancellationToken) + { + Guard.Against.Null(command, nameof(command)); + + var passengerReadModel = _mapper.Map(command); + + var passenger = await _passengerReadDbContext.Passenger.AsQueryable() + .FirstOrDefaultAsync(x => x.PassengerId == command.Id && !x.IsDeleted, cancellationToken); + + if (passenger is not null) + { + await _passengerReadDbContext.Passenger.UpdateOneAsync( + x => x.PassengerId == passengerReadModel.PassengerId, + Builders.Update + .Set(x => x.PassengerId, passengerReadModel.PassengerId) + .Set(x => x.Age, passengerReadModel.Age) + .Set(x => x.Name, passengerReadModel.Name) + .Set(x => x.IsDeleted, passengerReadModel.IsDeleted) + .Set(x => x.PassengerType, passengerReadModel.PassengerType) + .Set(x => x.PassportNumber, passengerReadModel.PassportNumber), + cancellationToken: cancellationToken); + } + else + { + await _passengerReadDbContext.Passenger.InsertOneAsync(passengerReadModel, + cancellationToken: cancellationToken); + } + + return Unit.Value; + } +} diff --git a/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs b/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs index 69b4d39..5a8a6f1 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Features/PassengerMappings.cs @@ -1,6 +1,10 @@ using AutoMapper; +using BuildingBlocks.Contracts.EventBus.Messages; +using BuildingBlocks.IdsGenerator; using Mapster; using Passenger.Passengers.Dtos; +using Passenger.Passengers.Features.CompleteRegisterPassenger.Reads; +using Passenger.Passengers.Models.Reads; namespace Passenger.Passengers.Features; @@ -8,5 +12,8 @@ public class PassengerMappings : IRegister { public void Register(TypeAdapterConfig config) { + config.NewConfig() + .Map(d => d.Id, s => SnowFlakIdGenerator.NewId()) + .Map(d => d.PassengerId, s => s.Id); } } diff --git a/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs b/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs index 02186a7..e818eb7 100644 --- a/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs +++ b/src/Services/Passenger/src/Passenger/Passengers/Models/Passenger.cs @@ -1,10 +1,11 @@ using BuildingBlocks.Core.Model; +using Passenger.Passengers.Events.Domain; namespace Passenger.Passengers.Models; -public class Passenger : Aggregate +public record Passenger : Aggregate { - public Passenger CompleteRegistrationPassenger(long id, string name, string passportNumber, PassengerType passengerType, int age) + public Passenger CompleteRegistrationPassenger(long id, string name, string passportNumber, PassengerType passengerType, int age, bool isDeleted = false) { var passenger = new Passenger { @@ -12,8 +13,15 @@ public class Passenger : Aggregate PassportNumber = passportNumber, PassengerType = passengerType, Age = age, - Id = id + Id = id, + IsDeleted = isDeleted }; + + var @event = new PassengerRegistrationCompletedDomainEvent(passenger.Id, passenger.Name, passenger.PassportNumber, + passenger.PassengerType, passenger.Age, passenger.IsDeleted); + + passenger.AddDomainEvent(@event); + return passenger; } @@ -21,6 +29,11 @@ public class Passenger : Aggregate public static Passenger Create(long id, string name, string passportNumber, bool isDeleted = false) { var passenger = new Passenger { Id = id, Name = name, PassportNumber = passportNumber, IsDeleted = isDeleted }; + + var @event = new PassengerCreatedDomainEvent(passenger.Id, passenger.Name, passenger.PassportNumber, passenger.IsDeleted); + + passenger.AddDomainEvent(@event); + return passenger; } diff --git a/src/Services/Passenger/src/Passenger/Passengers/Models/Reads/PassengerReadModel.cs b/src/Services/Passenger/src/Passenger/Passengers/Models/Reads/PassengerReadModel.cs new file mode 100644 index 0000000..ebe2ebe --- /dev/null +++ b/src/Services/Passenger/src/Passenger/Passengers/Models/Reads/PassengerReadModel.cs @@ -0,0 +1,12 @@ +namespace Passenger.Passengers.Models.Reads; + +public class PassengerReadModel +{ + public long Id { get; init; } + public long PassengerId { get; init; } + public string PassportNumber { get; private set; } + public string Name { get; private set; } + public PassengerType PassengerType { get; private set; } + public int Age { get; private set; } + public bool IsDeleted { get; init; } +}