Browse Source

Refactoring Domain Events so it is clear and differenciated versus Integration Events

pull/126/head
Cesar De la Torre 8 years ago
parent
commit
b9c1778d9d
12 changed files with 50 additions and 45 deletions
  1. +5
    -5
      src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCreatedDomainEventHandler.cs
  2. +5
    -5
      src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/PaymentMethodCheckedDomainEventHandler.cs
  3. +2
    -2
      src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs
  4. +2
    -2
      src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs
  5. +7
    -4
      src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs
  6. +2
    -2
      src/Services/Ordering/Ordering.Domain/Events/OrderCreatedDomainEvent.cs
  7. +2
    -2
      src/Services/Ordering/Ordering.Domain/Events/PaymentMethodCheckedDomainEvent.cs
  8. +8
    -8
      src/Services/Ordering/Ordering.Domain/SeedWork/Entity.cs
  9. +3
    -3
      src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs
  10. +6
    -4
      src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs
  11. +1
    -1
      test/Services/UnitTest/Ordering/Domain/BuyerAggregateTest.cs
  12. +7
    -7
      test/Services/UnitTest/Ordering/Domain/OrderAggregateTest.cs

src/Services/Ordering/Ordering.API/Application/EventHandlers/OrderCreatedEventHandler.cs → src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/OrderCreatedDomainEventHandler.cs View File

@ -6,22 +6,22 @@ using Ordering.Domain.Events;
using System;
using System.Threading.Tasks;
namespace Ordering.API.Application.EventHandlers
namespace Ordering.API.Application.DomainEventHandlers
{
public class OrderCreatedEventHandler : IAsyncNotificationHandler<OrderCreated>
public class OrderCreatedDomainEventHandler : IAsyncNotificationHandler<OrderCreatedDomainEvent>
{
private readonly ILoggerFactory _logger;
private readonly IBuyerRepository<Buyer> _buyerRepository;
private readonly IIdentityService _identityService;
public OrderCreatedEventHandler(ILoggerFactory logger, IBuyerRepository<Buyer> buyerRepository, IIdentityService identityService)
public OrderCreatedDomainEventHandler(ILoggerFactory logger, IBuyerRepository<Buyer> buyerRepository, IIdentityService identityService)
{
_buyerRepository = buyerRepository ?? throw new ArgumentNullException(nameof(buyerRepository));
_identityService = identityService ?? throw new ArgumentNullException(nameof(identityService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(OrderCreated orderNotification)
public async Task Handle(OrderCreatedDomainEvent orderNotification)
{
var cardTypeId = orderNotification.CardTypeId != 0 ? orderNotification.CardTypeId : 1;
@ -46,7 +46,7 @@ namespace Ordering.API.Application.EventHandlers
await _buyerRepository.UnitOfWork
.SaveEntitiesAsync();
_logger.CreateLogger(nameof(OrderCreatedEventHandler)).LogTrace($"A new payment method has been successfully added for orderId: {orderNotification.Order.Id}.");
_logger.CreateLogger(nameof(OrderCreatedDomainEventHandler)).LogTrace($"A new payment method has been successfully added for orderId: {orderNotification.Order.Id}.");
}
}

src/Services/Ordering/Ordering.API/Application/EventHandlers/PaymentMethodCheckedEventHandler.cs → src/Services/Ordering/Ordering.API/Application/DomainEventHandlers/PaymentMethodCheckedDomainEventHandler.cs View File

@ -5,19 +5,19 @@ using Ordering.Domain.Events;
using System;
using System.Threading.Tasks;
namespace Ordering.API.Application.EventHandlers
namespace Ordering.API.Application.DomainEventHandlers
{
public class PaymentMethodCheckedEventHandler : IAsyncNotificationHandler<PaymentMethodChecked>
public class PaymentMethodCheckedDomainEventHandler : IAsyncNotificationHandler<PaymentMethodCheckedDomainEvent>
{
private readonly IOrderRepository<Order> _orderRepository;
private readonly ILoggerFactory _logger;
public PaymentMethodCheckedEventHandler(IOrderRepository<Order> orderRepository, ILoggerFactory logger)
public PaymentMethodCheckedDomainEventHandler(IOrderRepository<Order> orderRepository, ILoggerFactory logger)
{
_orderRepository = orderRepository ?? throw new ArgumentNullException(nameof(orderRepository));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public async Task Handle(PaymentMethodChecked paymentMethodNotification)
public async Task Handle(PaymentMethodCheckedDomainEvent paymentMethodNotification)
{
var orderToUpdate = await _orderRepository.GetAsync(paymentMethodNotification.OrderId);
orderToUpdate.SetBuyerId(paymentMethodNotification.Buyer.Id);
@ -26,7 +26,7 @@ namespace Ordering.API.Application.EventHandlers
await _orderRepository.UnitOfWork
.SaveEntitiesAsync();
_logger.CreateLogger(nameof(PaymentMethodCheckedEventHandler))
_logger.CreateLogger(nameof(PaymentMethodCheckedDomainEventHandler))
.LogTrace($"Order with Id: {paymentMethodNotification.OrderId} has been successfully updated with a new payment method id: { paymentMethodNotification.Payment.Id }");
}
}

+ 2
- 2
src/Services/Ordering/Ordering.API/Infrastructure/AutofacModules/MediatorModule.cs View File

@ -3,7 +3,7 @@ using Autofac.Core;
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Decorators;
using Ordering.API.Application.EventHandlers;
using Ordering.API.Application.DomainEventHandlers;
using Ordering.Domain.Events;
using System.Collections.Generic;
using System.Linq;
@ -24,7 +24,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
.Select(i => new KeyedService("IAsyncRequestHandler", i)));
builder
.RegisterAssemblyTypes(typeof(OrderCreatedEventHandler).GetTypeInfo().Assembly)
.RegisterAssemblyTypes(typeof(OrderCreatedDomainEventHandler).GetTypeInfo().Assembly)
.Where(t => t.IsClosedTypeOf(typeof(IAsyncNotificationHandler<>)))
.AsImplementedInterfaces();


+ 2
- 2
src/Services/Ordering/Ordering.Domain/AggregatesModel/BuyerAggregate/Buyer.cs View File

@ -33,7 +33,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
if (existingPayment != null)
{
AddEvent(new PaymentMethodChecked(this, existingPayment, orderId));
AddDomainEvent(new PaymentMethodCheckedDomainEvent(this, existingPayment, orderId));
return existingPayment;
}
else
@ -41,7 +41,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.B
var payment = new PaymentMethod(cardTypeId, alias, cardNumber, securityNumber, cardHolderName, expiration);
_paymentMethods.Add(payment);
AddEvent(new PaymentMethodChecked(this, payment, orderId));
AddDomainEvent(new PaymentMethodCheckedDomainEvent(this, payment, orderId));
return payment;
}
}


+ 7
- 4
src/Services/Ordering/Ordering.Domain/AggregatesModel/OrderAggregate/Order.cs View File

@ -51,7 +51,10 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
_orderStatusId = OrderStatus.InProcess.Id;
_orderDate = DateTime.UtcNow;
Address = address;
AddCreatedOrderEvent(cardTypeId, cardNumber,
// Add the OrderCreatedEvent to the domain events collection
// to be raised/dispatched when comitting changes into the Database [ After DbContext.SaveChanges() ]
AddOrderCreatedDomainEvent(cardTypeId, cardNumber,
cardSecurityNumber, cardHolderName, cardExpiration);
}
@ -93,14 +96,14 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.O
_buyerId = id;
}
private void AddCreatedOrderEvent(int cardTypeId, string cardNumber,
private void AddOrderCreatedDomainEvent(int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName, DateTime cardExpiration)
{
var @orderCreatedEvent = new OrderCreated(
var orderCreatedDomainEvent = new OrderCreatedDomainEvent(
this, cardTypeId, cardNumber, cardSecurityNumber,
cardHolderName, cardExpiration);
AddEvent(@orderCreatedEvent);
AddDomainEvent(orderCreatedDomainEvent);
}
}
}

src/Services/Ordering/Ordering.Domain/Events/OrderCreated.cs → src/Services/Ordering/Ordering.Domain/Events/OrderCreatedDomainEvent.cs View File

@ -9,7 +9,7 @@ namespace Ordering.Domain.Events
/// <summary>
/// Event used when an order is created
/// </summary>
public class OrderCreated
public class OrderCreatedDomainEvent
: IAsyncNotification
{
public int CardTypeId { get; private set; }
@ -19,7 +19,7 @@ namespace Ordering.Domain.Events
public DateTime CardExpiration { get; private set; }
public Order Order { get; private set; }
public OrderCreated(Order order,
public OrderCreatedDomainEvent(Order order,
int cardTypeId, string cardNumber,
string cardSecurityNumber, string cardHolderName,
DateTime cardExpiration)

src/Services/Ordering/Ordering.Domain/Events/PaymentMethodChecked.cs → src/Services/Ordering/Ordering.Domain/Events/PaymentMethodCheckedDomainEvent.cs View File

@ -6,14 +6,14 @@ using System.Text;
namespace Ordering.Domain.Events
{
public class PaymentMethodChecked
public class PaymentMethodCheckedDomainEvent
: IAsyncNotification
{
public Buyer Buyer { get; private set; }
public PaymentMethod Payment { get; private set; }
public int OrderId { get; private set; }
public PaymentMethodChecked(Buyer buyer, PaymentMethod payment, int orderId)
public PaymentMethodCheckedDomainEvent(Buyer buyer, PaymentMethod payment, int orderId)
{
Buyer = buyer;
Payment = payment;

+ 8
- 8
src/Services/Ordering/Ordering.Domain/SeedWork/Entity.cs View File

@ -10,7 +10,7 @@
int? _requestedHashCode;
int _Id;
private List<IAsyncNotification> _events;
private List<IAsyncNotification> _domainEvents;
public virtual int Id
{
@ -24,17 +24,17 @@
}
}
public List<IAsyncNotification> Events => _events;
public void AddEvent(IAsyncNotification eventItem)
public List<IAsyncNotification> DomainEvents => _domainEvents;
public void AddDomainEvent(IAsyncNotification eventItem)
{
_events = _events ?? new List<IAsyncNotification>();
_events.Add(eventItem);
_domainEvents = _domainEvents ?? new List<IAsyncNotification>();
_domainEvents.Add(eventItem);
}
public void RemoveEvent(IAsyncNotification eventItem)
public void RemoveDomainEvent(IAsyncNotification eventItem)
{
if (_events is null) return;
_events.Remove(eventItem);
if (_domainEvents is null) return;
_domainEvents.Remove(eventItem);
}
public bool IsTransient()


+ 3
- 3
src/Services/Ordering/Ordering.Infrastructure/MediatorExtension.cs View File

@ -10,9 +10,9 @@ namespace Ordering.Infrastructure
{
public static async Task RaiseDomainEventsAsync(this IMediator mediator, OrderingContext ctx)
{
var domainEntities = ctx.ChangeTracker.Entries<Entity>().Where(x => x.Entity.Events != null && x.Entity.Events.Any());
var domainEvents = domainEntities.SelectMany(x => x.Entity.Events).ToList();
domainEntities.ToList().ForEach(entity => entity.Entity.Events.Clear());
var domainEntities = ctx.ChangeTracker.Entries<Entity>().Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any());
var domainEvents = domainEntities.SelectMany(x => x.Entity.DomainEvents).ToList();
domainEntities.ToList().ForEach(entity => entity.Entity.DomainEvents.Clear());
var tasks = domainEvents
.Select(async (domainEvent) => {


+ 6
- 4
src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs View File

@ -74,7 +74,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
buyerConfiguration.HasKey(b => b.Id);
buyerConfiguration.Ignore(b => b.Events);
buyerConfiguration.Ignore(b => b.DomainEvents);
buyerConfiguration.Property(b => b.Id)
.ForSqlServerUseSequenceHiLo("buyerseq", DEFAULT_SCHEMA);
@ -102,7 +102,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
paymentConfiguration.HasKey(b => b.Id);
paymentConfiguration.Ignore(b => b.Events);
paymentConfiguration.Ignore(b => b.DomainEvents);
paymentConfiguration.Property(b => b.Id)
.ForSqlServerUseSequenceHiLo("paymentseq", DEFAULT_SCHEMA);
@ -139,7 +139,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
orderConfiguration.HasKey(o => o.Id);
orderConfiguration.Ignore(b => b.Events);
orderConfiguration.Ignore(b => b.DomainEvents);
orderConfiguration.Property(o => o.Id)
.ForSqlServerUseSequenceHiLo("orderseq", DEFAULT_SCHEMA);
@ -176,7 +176,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
orderItemConfiguration.HasKey(o => o.Id);
orderItemConfiguration.Ignore(b => b.Events);
orderItemConfiguration.Ignore(b => b.DomainEvents);
orderItemConfiguration.Property(o => o.Id)
.ForSqlServerUseSequenceHiLo("orderitemseq");
@ -238,6 +238,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure
public async Task<int> SaveEntitiesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
var result = await base.SaveChangesAsync();
// Dispatch the Domain Events collection right after saving/commiting data into the database
await _mediator.RaiseDomainEventsAsync(this);
return result;
}


+ 1
- 1
test/Services/UnitTest/Ordering/Domain/BuyerAggregateTest.cs View File

@ -122,6 +122,6 @@ public class BuyerAggregateTest
fakeBuyer.AddPaymentMethod(cardTypeId, alias, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration, orderId);
//Assert
Assert.Equal(fakeBuyer.Events.Count, expectedResult);
Assert.Equal(fakeBuyer.DomainEvents.Count, expectedResult);
}
}

+ 7
- 7
test/Services/UnitTest/Ordering/Domain/OrderAggregateTest.cs View File

@ -112,7 +112,7 @@ public class OrderAggregateTest
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
//Assert
Assert.Equal(fakeOrder.Events.Count, expectedResult);
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult);
}
[Fact]
@ -133,9 +133,9 @@ public class OrderAggregateTest
//Act
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
fakeOrder.AddEvent(new OrderCreated(fakeOrder,cardTypeId,cardNumber,cardSecurityNumber,cardHolderName,cardExpiration));
fakeOrder.AddDomainEvent(new OrderCreatedDomainEvent(fakeOrder,cardTypeId,cardNumber,cardSecurityNumber,cardHolderName,cardExpiration));
//Assert
Assert.Equal(fakeOrder.Events.Count, expectedResult);
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult);
}
[Fact]
@ -153,13 +153,13 @@ public class OrderAggregateTest
var cardHolderName = "FakeName";
var cardExpiration = DateTime.Now.AddYears(1);
var fakeOrder = new Order(new Address(street, city, state, country, zipcode), cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
var @fakeEvent = new OrderCreated(fakeOrder, cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
var @fakeEvent = new OrderCreatedDomainEvent(fakeOrder, cardTypeId, cardNumber, cardSecurityNumber, cardHolderName, cardExpiration);
var expectedResult = 1;
//Act
fakeOrder.AddEvent(@fakeEvent);
fakeOrder.RemoveEvent(@fakeEvent);
fakeOrder.AddDomainEvent(@fakeEvent);
fakeOrder.RemoveDomainEvent(@fakeEvent);
//Assert
Assert.Equal(fakeOrder.Events.Count, expectedResult);
Assert.Equal(fakeOrder.DomainEvents.Count, expectedResult);
}
}

Loading…
Cancel
Save