@ -1,15 +1,10 @@
using MediatR ;
using Microsoft.EntityFrameworkCore ;
using Microsoft.EntityFrameworkCore.Storage ;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions ;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services ;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate ;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure ;
using Microsoft.Extensions.Logging ;
using Ordering.API.IntegrationEvents ;
using Ordering.API.IntegrationEvents.Events ;
using Ordering.Domain.Events ;
using System ;
using System.Data.Common ;
using System.Threading.Tasks ;
namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVerified
@ -18,17 +13,15 @@ namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVeri
: IAsyncNotificationHandler < BuyerAndPaymentMethodVerifiedDomainEvent >
{
private readonly IOrderRepository _orderRepository ;
private readonly ILoggerFactory _logger ;
private readonly Func < DbConnection , IIntegrationEventLogService > _integrationEventLogServiceFactory ;
private readonly IEventBus _eventBus ;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService ;
private readonly ILoggerFactory _logger ;
public UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler (
IOrderRepository orderRepository , ILoggerFactory logger , IEventBus eventBus ,
Func < DbConnection , IIntegrationEventLogService > integrationEventLogServiceFactory )
IOrderRepository orderRepository , ILoggerFactory logger ,
IOrderingIntegrationEventService orderingIntegrationEventService )
{
_orderRepository = orderRepository ? ? throw new ArgumentNullException ( nameof ( orderRepository ) ) ;
_integrationEventLogServiceFactory = integrationEventLogServiceFactory ? ? throw new ArgumentNullException ( nameof ( integrationEventLogServiceFactory ) ) ;
_eventBus = eventBus ? ? throw new ArgumentNullException ( nameof ( eventBus ) ) ;
_orderingIntegrationEventService = orderingIntegrationEventService ? ? throw new ArgumentNullException ( nameof ( orderingIntegrationEventService ) ) ;
_logger = logger ? ? throw new ArgumentNullException ( nameof ( logger ) ) ;
}
@ -42,28 +35,18 @@ namespace Ordering.API.Application.DomainEventHandlers.BuyerAndPaymentMethodVeri
orderToUpdate . SetPaymentId ( buyerPaymentMethodVerifiedEvent . Payment . Id ) ;
var orderStartedIntegrationEvent = new OrderStartedIntegrationEvent ( buyerPaymentMethodVerifiedEvent . Buyer . IdentityGuid ) ;
//Use of an EF Core resiliency strategy when using multiple DbContexts within an explicit BeginTransaction():
//See: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
var orderingContext = _orderRepository . UnitOfWork as OrderingContext ;
var strategy = orderingContext . Database . CreateExecutionStrategy ( ) ;
var eventLogService = _integrationEventLogServiceFactory ( orderingContext . Database . GetDbConnection ( ) ) ;
await strategy . ExecuteAsync ( async ( ) = >
{
// Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transaction
using ( var transaction = orderingContext . Database . BeginTransaction ( ) )
{
await _orderRepository . UnitOfWork . SaveEntitiesAsync ( ) ;
await eventLogService . SaveEventAsync ( orderStartedIntegrationEvent , orderingContext . Database . CurrentTransaction . GetDbTransaction ( ) ) ;
transaction . Commit ( ) ;
}
} ) ;
// Using a local transaction to achieve atomicity between original Ordering database operation and
// the IntegrationEventLog. Only saving event if order has been successfully persisted to db
await _orderingIntegrationEventService
. SaveEventAsync ( orderStartedIntegrationEvent ) ;
_logger . CreateLogger ( nameof ( UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler ) )
. LogTrace ( $"Order with Id: {buyerPaymentMethodVerifiedEvent.OrderId} has been successfully updated with a payment method id: { buyerPaymentMethodVerifiedEvent.Payment.Id }" ) ;
// Publish ordering integration event and mark it as published
await _orderingIntegrationEventService
. PublishAsync ( orderStartedIntegrationEvent ) ;
_eventBus . Publish ( orderStartedIntegrationEvent ) ;
await eventLogService . MarkEventAsPublishedAsync ( orderStartedIntegrationEvent ) ;
_logger . CreateLogger ( nameof ( UpdateOrderWhenBuyerAndPaymentMethodVerifiedDomainEventHandler ) )
. LogTrace ( $"Order with Id: {buyerPaymentMethodVerifiedEvent.OrderId} has been successfully updated with a payment method id: { buyerPaymentMethodVerifiedEvent.Payment.Id }" ) ;
}
}
}