refactor: Refactor value objects

This commit is contained in:
Pc 2023-06-12 19:13:50 +03:30
parent 728b8a7a57
commit ef53893263
29 changed files with 59 additions and 82 deletions

View File

@ -4,6 +4,6 @@ namespace BuildingBlocks.Core;
public interface IEventMapper
{
IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event);
IInternalCommand MapToInternalCommand(IDomainEvent @event);
IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event);
IInternalCommand? MapToInternalCommand(IDomainEvent @event);
}

View File

@ -17,7 +17,7 @@ public class AuthHeaderHandler : DelegatingHandler
{
var token = (_httpContext?.HttpContext?.Request.Headers["Authorization"])?.ToString();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", "", StringComparison.Ordinal));
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token?.Replace("Bearer ", ""));
return base.SendAsync(request, cancellationToken);
}

View File

@ -200,10 +200,7 @@ public class PersistMessageProcessor : IPersistMessageProcessor
deliveryType),
cancellationToken);
await _persistMessageDbContext.RetryOnFailure(async () =>
{
await _persistMessageDbContext.SaveChangesAsync(cancellationToken);
});
await _persistMessageDbContext.SaveChangesAsync(cancellationToken);
_logger.LogInformation(
"Message with id: {MessageID} and delivery type: {DeliveryType} saved in persistence message store.",
@ -219,9 +216,6 @@ public class PersistMessageProcessor : IPersistMessageProcessor
_persistMessageDbContext.PersistMessages.Update(message);
await _persistMessageDbContext.RetryOnFailure(async () =>
{
await _persistMessageDbContext.SaveChangesAsync(cancellationToken);
});
await _persistMessageDbContext.SaveChangesAsync(cancellationToken);
}
}

View File

@ -92,10 +92,6 @@ public class TestFixture<TEntryPoint> : IAsyncLifetime
services.AddSingleton<PersistMessageBackgroundService>();
// // remove persist-message processor background service
// var descriptor = services.Single(s => s.ImplementationType == typeof(PersistMessageBackgroundService));
// services.Remove(descriptor);
// add authentication using a fake jwt bearer - we can use SetAdminUser method to set authenticate user to existing HttContextAccessor
// https://github.com/webmotions/fake-authentication-jwtbearer
// https://github.com/webmotions/fake-authentication-jwtbearer/issues/14

View File

@ -100,7 +100,7 @@ internal class CreateBookingCommandHandler : ICommandHandler<CreateBooking, Crea
Guard.Against.Null(command, nameof(command));
var flight =
await _flightGrpcServiceClient.GetByIdAsync(new Flight.GetByIdRequest { Id = command.FlightId.ToString() });
await _flightGrpcServiceClient.GetByIdAsync(new Flight.GetByIdRequest { Id = command.FlightId.ToString() }, cancellationToken: cancellationToken);
if (flight is null)
{
@ -108,11 +108,10 @@ internal class CreateBookingCommandHandler : ICommandHandler<CreateBooking, Crea
}
var passenger =
await _passengerGrpcServiceClient.GetByIdAsync(
new Passenger.GetByIdRequest { Id = command.PassengerId.ToString() });
await _passengerGrpcServiceClient.GetByIdAsync(new Passenger.GetByIdRequest { Id = command.PassengerId.ToString() }, cancellationToken: cancellationToken);
var emptySeat = (await _flightGrpcServiceClient
.GetAvailableSeatsAsync(new GetAvailableSeatsRequest { FlightId = command.FlightId.ToString() })
.GetAvailableSeatsAsync(new GetAvailableSeatsRequest { FlightId = command.FlightId.ToString() }, cancellationToken: cancellationToken)
.ResponseAsync)
?.SeatDtos?.FirstOrDefault();
@ -136,7 +135,7 @@ internal class CreateBookingCommandHandler : ICommandHandler<CreateBooking, Crea
await _flightGrpcServiceClient.ReserveSeatAsync(new ReserveSeatRequest
{
FlightId = flight.FlightDto.Id, SeatNumber = emptySeat?.SeatNumber
});
}, cancellationToken: cancellationToken);
var result = await _eventStoreDbRepository.Add(
aggrigate,

View File

@ -8,7 +8,7 @@ using Booking.Features.CreatingBook.Commands.V1;
public sealed class EventMapper : IEventMapper
{
public IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event)
public IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event)
{
return @event switch
{
@ -17,7 +17,7 @@ public sealed class EventMapper : IEventMapper
};
}
public IInternalCommand MapToInternalCommand(IDomainEvent @event)
public IInternalCommand? MapToInternalCommand(IDomainEvent @event)
{
return @event switch
{

View File

@ -53,7 +53,7 @@ public class CreateAircraftEndpoint : IMinimalEndpoint
return Results.Ok(response);
})
.RequireAuthorization(nameof(ApiScope))
//.RequireAuthorization(nameof(ApiScope))
.WithName("CreateAircraft")
.WithApiVersionSet(builder.NewApiVersionSet("Flight").Build())
.Produces<CreateAircraftResponseDto>()
@ -90,9 +90,8 @@ internal class CreateAircraftHandler : IRequestHandler<CreateAircraft, CreateAir
{
Guard.Against.Null(request, nameof(request));
var aircraft = await _flightDbContext.Aircraft.AsNoTracking().SingleOrDefaultAsync(
a => a.Model.Value.Equals(Model.Of(request.Model)), cancellationToken);
var aircraft = await _flightDbContext.Aircraft.SingleOrDefaultAsync(
a => a.Model.Value == request.Model, cancellationToken);
if (aircraft is not null)
{
@ -101,7 +100,7 @@ internal class CreateAircraftHandler : IRequestHandler<CreateAircraft, CreateAir
var aircraftEntity = Aircraft.Create(AircraftId.Of(request.Id), Name.Of(request.Name), Model.Of(request.Model), ManufacturingYear.Of(request.ManufacturingYear));
var newAircraft = (await _flightDbContext.Aircraft.AddAsync(aircraftEntity, cancellationToken))?.Entity;
var newAircraft = (await _flightDbContext.Aircraft.AddAsync(aircraftEntity, cancellationToken)).Entity;
return new CreateAircraftResult(newAircraft.Id);
}

View File

@ -37,7 +37,8 @@ public class CreateAircraftMongoHandler : ICommandHandler<CreateAircraftMongo>
var aircraftReadModel = _mapper.Map<AircraftReadModel>(request);
var aircraft = await _flightReadDbContext.Aircraft.AsQueryable()
.FirstOrDefaultAsync(x => x.AircraftId == AircraftId.Of(aircraftReadModel.AircraftId), cancellationToken);
.FirstOrDefaultAsync(x => x.AircraftId == aircraftReadModel.AircraftId &&
!x.IsDeleted, cancellationToken);
if (aircraft is not null)
{

View File

@ -97,8 +97,8 @@ internal class CreateAirportHandler : IRequestHandler<CreateAirport, CreateAirpo
var airportEntity = Models.Airport.Create(AirportId.Of(request.Id), Name.Of(request.Name), Address.Of(request.Address), Code.Of(request.Code));
var newAirport = (await _flightDbContext.Airports.AddAsync(airportEntity, cancellationToken))?.Entity;
var newAirport = (await _flightDbContext.Airports.AddAsync(airportEntity, cancellationToken)).Entity;
return new CreateAirportResult(newAirport.Id.Value);
return new CreateAirportResult(newAirport.Id);
}
}

View File

@ -36,7 +36,8 @@ internal class CreateAirportMongoHandler : ICommandHandler<CreateAirportMongo>
var airportReadModel = _mapper.Map<AirportReadModel>(request);
var aircraft = await _flightReadDbContext.Airport.AsQueryable()
.FirstOrDefaultAsync(x => x.AirportId == airportReadModel.AirportId, cancellationToken);
.FirstOrDefaultAsync(x => x.AirportId == airportReadModel.AirportId &&
!x.IsDeleted, cancellationToken);
if (aircraft is not null)
{

View File

@ -1,14 +1,8 @@
namespace Flight.Airports.ValueObjects;
using System.Linq;
using Exceptions;
public class Address
{
public string Street { get; }
public string City { get; }
public string State { get; }
public string ZipCode { get; }
public string Country { get; }
public string Value { get; }
public Address(string value)
@ -20,17 +14,6 @@ public class Address
Value = value;
}
public Address(string street, string city, string state, string zipCode, string country)
{
Street = street?.Trim();
City = city?.Trim();
State = state?.Trim();
ZipCode = zipCode?.Trim();
Country = country?.Trim();
Value = string.Join(", ", new[] { Street, City, State, ZipCode, Country }.Where(s => !string.IsNullOrWhiteSpace(s)));
}
public static Address Of(string value)
{
return new Address(value);

View File

@ -36,17 +36,20 @@ public class FlightConfiguration : IEntityTypeConfiguration<Flights.Models.Fligh
builder
.HasOne<Aircraft>()
.WithMany()
.HasForeignKey(p => p.AircraftId);
.HasForeignKey(p => p.AircraftId)
.IsRequired();
builder
.HasOne<Airport>()
.WithMany()
.HasForeignKey(d => d.DepartureAirportId);
.HasForeignKey(d => d.DepartureAirportId)
.IsRequired();
builder
.HasOne<Airport>()
.WithMany()
.HasForeignKey(d => d.ArriveAirportId);
.HasForeignKey(d => d.ArriveAirportId)
.IsRequired();
builder.OwnsOne(

View File

@ -12,7 +12,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace Flight.Data.Migrations
{
[DbContext(typeof(FlightDbContext))]
[Migration("20230611213200_initial")]
[Migration("20230611230948_initial")]
partial class initial
{
/// <inheritdoc />

View File

@ -16,7 +16,7 @@ using Seats.Features.ReservingSeat.Commands.V1;
// ref: https://www.ledjonbehluli.com/posts/domain_to_integration_event/
public sealed class EventMapper : IEventMapper
{
public IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event)
public IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event)
{
return @event switch
{
@ -31,7 +31,7 @@ public sealed class EventMapper : IEventMapper
};
}
public IInternalCommand MapToInternalCommand(IDomainEvent @event)
public IInternalCommand? MapToInternalCommand(IDomainEvent @event)
{
return @event switch
{

View File

@ -119,8 +119,8 @@ internal class CreateFlightHandler : ICommandHandler<CreateFlight, CreateFlightR
ArriveDate.Of(request.ArriveDate), AirportId.Of(request.ArriveAirportId), DurationMinutes.Of(request.DurationMinutes), FlightDate.Of(request.FlightDate), request.Status,
Price.Of(request.Price));
var newFlight = (await _flightDbContext.Flights.AddAsync(flightEntity, cancellationToken))?.Entity;
var newFlight = (await _flightDbContext.Flights.AddAsync(flightEntity, cancellationToken)).Entity;
return new CreateFlightResult(newFlight.Id.Value);
return new CreateFlightResult(newFlight.Id);
}
}

View File

@ -74,7 +74,8 @@ internal class DeleteFlightHandler : ICommandHandler<DeleteFlight, DeleteFlightR
{
Guard.Against.Null(request, nameof(request));
var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == FlightId.Of(request.Id), cancellationToken);
var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == request.Id, cancellationToken);
if (flight is null)
{
throw new FlightNotFountException();
@ -84,8 +85,8 @@ internal class DeleteFlightHandler : ICommandHandler<DeleteFlight, DeleteFlightR
flight.DepartureDate, flight.ArriveDate, flight.ArriveAirportId, flight.DurationMinutes,
flight.FlightDate, flight.Status, flight.Price);
var deleteFlight = _flightDbContext.Flights.Remove(flight)?.Entity;
var deleteFlight = _flightDbContext.Flights.Update(flight).Entity;
return new DeleteFlightResult(deleteFlight.Id.Value);
return new DeleteFlightResult(deleteFlight.Id);
}
}

View File

@ -104,7 +104,7 @@ internal class UpdateFlightHandler : ICommandHandler<UpdateFlight, UpdateFlightR
{
Guard.Against.Null(request, nameof(request));
var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == FlightId.Of(request.Id),
var flight = await _flightDbContext.Flights.SingleOrDefaultAsync(x => x.Id == request.Id,
cancellationToken);
if (flight is null)
@ -118,8 +118,8 @@ internal class UpdateFlightHandler : ICommandHandler<UpdateFlight, UpdateFlightR
ArriveDate.Of(request.ArriveDate), AirportId.Of(request.ArriveAirportId), DurationMinutes.Of(request.DurationMinutes), FlightDate.Of(request.FlightDate), request.Status,
Price.Of(request.Price), request.IsDeleted);
var updateFlight = (_flightDbContext.Flights.Update(flight))?.Entity;
var updateFlight = (_flightDbContext.Flights.Update(flight)).Entity;
return new UpdateFlightResult(updateFlight.Id.Value);
return new UpdateFlightResult(updateFlight.Id);
}
}

View File

@ -97,7 +97,8 @@ internal class CreateSeatCommandHandler : IRequestHandler<CreateSeat, CreateSeat
{
Guard.Against.Null(command, nameof(command));
var seat = await _flightDbContext.Seats.AsNoTracking().SingleOrDefaultAsync(x => x.Id.Equals(SeatId.Of(command.Id)), cancellationToken);
var seat = await _flightDbContext.Seats.SingleOrDefaultAsync(x => x.Id == command.Id, cancellationToken);
if (seat is not null)
{
throw new SeatAlreadyExistException();
@ -105,8 +106,8 @@ internal class CreateSeatCommandHandler : IRequestHandler<CreateSeat, CreateSeat
var seatEntity = Seat.Create(SeatId.Of(command.Id), SeatNumber.Of(command.SeatNumber), command.Type, command.Class, FlightId.Of(command.FlightId));
var newSeat = (await _flightDbContext.Seats.AddAsync(seatEntity, cancellationToken))?.Entity;
var newSeat = (await _flightDbContext.Seats.AddAsync(seatEntity, cancellationToken)).Entity;
return new CreateSeatResult(newSeat.Id.Value);
return new CreateSeatResult(newSeat.Id);
}
}

View File

@ -37,7 +37,8 @@ public class CreateSeatMongoHandler : ICommandHandler<CreateSeatMongo>
var seatReadModel = _mapper.Map<SeatReadModel>(request);
var seat = await _flightReadDbContext.Seat.AsQueryable()
.FirstOrDefaultAsync(x => x.SeatId == seatReadModel.SeatId, cancellationToken);
.FirstOrDefaultAsync(x => x.SeatId == seatReadModel.SeatId &&
!x.IsDeleted, cancellationToken);
if (seat is not null)
{

View File

@ -84,10 +84,9 @@ internal class ReserveSeatCommandHandler : IRequestHandler<ReserveSeat, ReserveS
{
Guard.Against.Null(command, nameof(command));
var seat = await _flightDbContext.Seats.AsNoTracking().SingleOrDefaultAsync(
x => x.SeatNumber.Value.Equals(SeatNumber.Of(command.SeatNumber)) && x.FlightId.Equals(FlightId.Of(command.FlightId)), cancellationToken);
var seat = await _flightDbContext.Seats.SingleOrDefaultAsync(
x => x.SeatNumber.Value == command.SeatNumber &&
x.FlightId == command.FlightId, cancellationToken);
if (seat is null)
{
@ -96,7 +95,7 @@ internal class ReserveSeatCommandHandler : IRequestHandler<ReserveSeat, ReserveS
var reserveSeat = await seat.ReserveSeat(seat);
var updatedSeat = (_flightDbContext.Seats.Update(reserveSeat))?.Entity;
var updatedSeat = (_flightDbContext.Seats.Update(reserveSeat)).Entity;
return new ReserveSeatResult(updatedSeat.Id);
}

View File

@ -30,6 +30,5 @@ public class CreateFlightTests : FlightIntegrationTestBase
response?.Id.Should().Be(command.Id);
(await Fixture.WaitForPublishing<FlightCreated>()).Should().Be(true);
(await Fixture.WaitForConsuming<FlightCreated>()).Should().Be(true);
}
}

View File

@ -5,7 +5,7 @@ using BuildingBlocks.Core.Event;
public sealed class EventMapper : IEventMapper
{
public IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event)
public IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event)
{
return @event switch
{
@ -13,7 +13,7 @@ public sealed class EventMapper : IEventMapper
};
}
public IInternalCommand MapToInternalCommand(IDomainEvent @event)
public IInternalCommand? MapToInternalCommand(IDomainEvent @event)
{
return @event switch
{

View File

@ -9,7 +9,7 @@ using Passengers.Features.CompletingRegisterPassenger.V1;
public sealed class EventMapper : IEventMapper
{
public IIntegrationEvent MapToIntegrationEvent(IDomainEvent @event)
public IIntegrationEvent? MapToIntegrationEvent(IDomainEvent @event)
{
return @event switch
{
@ -19,7 +19,7 @@ public sealed class EventMapper : IEventMapper
};
}
public IInternalCommand MapToInternalCommand(IDomainEvent @event)
public IInternalCommand? MapToInternalCommand(IDomainEvent @event)
{
return @event switch
{

View File

@ -38,7 +38,7 @@ public class RegisterNewUserHandler : IConsumer<UserCreated>
_logger.LogInformation($"consumer for {nameof(UserCreated).Underscore()} in {_options.Name}");
var passengerExist =
await _passengerDbContext.Passengers.AnyAsync(x => x.PassportNumber.Value == PassportNumber.Of(context.Message.PassportNumber).Value);
await _passengerDbContext.Passengers.AnyAsync(x => x.PassportNumber.Value == context.Message.PassportNumber);
if (passengerExist)
{

View File

@ -97,7 +97,7 @@ internal class CompleteRegisterPassengerCommandHandler : ICommandHandler<Complet
Guard.Against.Null(request, nameof(request));
var passenger = await _passengerDbContext.Passengers.AsNoTracking().SingleOrDefaultAsync(
x => x.PassportNumber.Value.Equals(PassportNumber.Of(request.PassportNumber).Value), cancellationToken);
x => x.PassportNumber.Value == request.PassportNumber, cancellationToken);
if (passenger is null)
@ -108,7 +108,7 @@ internal class CompleteRegisterPassengerCommandHandler : ICommandHandler<Complet
var passengerEntity = passenger.CompleteRegistrationPassenger(passenger.Id, passenger.Name,
passenger.PassportNumber, request.PassengerType, Age.Of(request.Age));
var updatePassenger = _passengerDbContext.Passengers.Update(passengerEntity)?.Entity;
var updatePassenger = _passengerDbContext.Passengers.Update(passengerEntity).Entity;
var passengerDto = _mapper.Map<PassengerDto>(updatePassenger);

View File

@ -35,7 +35,7 @@ internal class CompleteRegisterPassengerMongoHandler : ICommandHandler<CompleteR
var passengerReadModel = _mapper.Map<PassengerReadModel>(request);
var passenger = await _passengerReadDbContext.Passenger.AsQueryable()
.FirstOrDefaultAsync(x => x.PassengerId == PassengerId.Of(passengerReadModel.PassengerId) && !x.IsDeleted, cancellationToken);
.FirstOrDefaultAsync(x => x.PassengerId == passengerReadModel.PassengerId && !x.IsDeleted, cancellationToken);
if (passenger is not null)
{

View File

@ -75,7 +75,7 @@ internal class GetPassengerByIdHandler : IQueryHandler<GetPassengerById, GetPass
var passenger =
await _passengerReadDbContext.Passenger.AsQueryable()
.SingleOrDefaultAsync(x => x.PassengerId == PassengerId.Of(query.Id) && x.IsDeleted == false, cancellationToken);
.SingleOrDefaultAsync(x => x.PassengerId == query.Id && x.IsDeleted == false, cancellationToken);
if (passenger is null)
{

View File

@ -26,7 +26,7 @@ public record Passenger : Aggregate<PassengerId>
};
var @event = new PassengerRegistrationCompletedDomainEvent(passenger.Id, passenger.Name, passenger.PassportNumber,
passenger.PassengerType, passenger.Age.Value, passenger.IsDeleted);
passenger.PassengerType, passenger.Age, passenger.IsDeleted);
passenger.AddDomainEvent(@event);