Send commands for modifying state in IntegrationEventHandlers

This commit is contained in:
Ramón Tomás 2018-10-08 10:14:23 +02:00
parent 9adda02b18
commit adafb9abf4
13 changed files with 347 additions and 46 deletions

View File

@ -0,0 +1,21 @@
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
public class SetAwaitingValidationOrderStatusCommand : IRequest<bool>
{
[DataMember]
public int OrderNumber { get; private set; }
public SetAwaitingValidationOrderStatusCommand(int orderNumber)
{
OrderNumber = orderNumber;
}
}
}

View File

@ -0,0 +1,52 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
using System.Threading;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
// Regular CommandHandler
public class SetAwaitingValidationOrderStatusCommandHandler : IRequestHandler<SetAwaitingValidationOrderStatusCommand, bool>
{
private readonly IOrderRepository _orderRepository;
public SetAwaitingValidationOrderStatusCommandHandler(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
/// <summary>
/// Handler which processes the command when
/// graceperiod has finished
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public async Task<bool> Handle(SetAwaitingValidationOrderStatusCommand command, CancellationToken cancellationToken)
{
var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber);
if(orderToUpdate == null)
{
return false;
}
orderToUpdate.SetAwaitingValidationStatus();
return await _orderRepository.UnitOfWork.SaveEntitiesAsync();
}
}
// Use for Idempotency in Command process
public class SetAwaitingValidationIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler<SetAwaitingValidationOrderStatusCommand, bool>
{
public SetAwaitingValidationIdentifiedOrderStatusCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
{
}
protected override bool CreateResultForDuplicateRequest()
{
return true; // Ignore duplicate requests for processing order.
}
}
}

View File

@ -0,0 +1,21 @@
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
public class SetPaidOrderStatusCommand : IRequest<bool>
{
[DataMember]
public int OrderNumber { get; private set; }
public SetPaidOrderStatusCommand(int orderNumber)
{
OrderNumber = orderNumber;
}
}
}

View File

@ -0,0 +1,55 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
using System.Threading;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
// Regular CommandHandler
public class SetPaidOrderStatusCommandHandler : IRequestHandler<SetPaidOrderStatusCommand, bool>
{
private readonly IOrderRepository _orderRepository;
public SetPaidOrderStatusCommandHandler(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
/// <summary>
/// Handler which processes the command when
/// Shipment service confirms the payment
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public async Task<bool> Handle(SetPaidOrderStatusCommand command, CancellationToken cancellationToken)
{
// Simulate a work time for validating the payment
await Task.Delay(10000);
var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber);
if(orderToUpdate == null)
{
return false;
}
orderToUpdate.SetPaidStatus();
return await _orderRepository.UnitOfWork.SaveEntitiesAsync();
}
}
// Use for Idempotency in Command process
public class SetPaidIdentifiedOrderStatusCommandHandler : IdentifiedCommandHandler<SetPaidOrderStatusCommand, bool>
{
public SetPaidIdentifiedOrderStatusCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
{
}
protected override bool CreateResultForDuplicateRequest()
{
return true; // Ignore duplicate requests for processing order.
}
}
}

View File

@ -0,0 +1,21 @@
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
public class SetStockConfirmedOrderStatusCommand : IRequest<bool>
{
[DataMember]
public int OrderNumber { get; private set; }
public SetStockConfirmedOrderStatusCommand(int orderNumber)
{
OrderNumber = orderNumber;
}
}
}

View File

@ -0,0 +1,55 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
using System.Threading;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
// Regular CommandHandler
public class SetStockConfirmedOrderStatusCommandHandler : IRequestHandler<SetStockConfirmedOrderStatusCommand, bool>
{
private readonly IOrderRepository _orderRepository;
public SetStockConfirmedOrderStatusCommandHandler(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
/// <summary>
/// Handler which processes the command when
/// Stock service confirms the request
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public async Task<bool> Handle(SetStockConfirmedOrderStatusCommand command, CancellationToken cancellationToken)
{
// Simulate a work time for confirming the stock
await Task.Delay(10000);
var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber);
if(orderToUpdate == null)
{
return false;
}
orderToUpdate.SetStockConfirmedStatus();
return await _orderRepository.UnitOfWork.SaveEntitiesAsync();
}
}
// Use for Idempotency in Command process
public class SetStockConfirmedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler<SetStockConfirmedOrderStatusCommand, bool>
{
public SetStockConfirmedOrderStatusIdenfifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
{
}
protected override bool CreateResultForDuplicateRequest()
{
return true; // Ignore duplicate requests for processing order.
}
}
}

View File

@ -0,0 +1,25 @@
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
public class SetStockRejectedOrderStatusCommand : IRequest<bool>
{
[DataMember]
public int OrderNumber { get; private set; }
[DataMember]
public List<int> OrderStockItems { get; private set; }
public SetStockRejectedOrderStatusCommand(int orderNumber, List<int> orderStockItems)
{
OrderNumber = orderNumber;
OrderStockItems = orderStockItems;
}
}
}

View File

@ -0,0 +1,56 @@
using MediatR;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
using System.Threading;
using System.Threading.Tasks;
namespace Ordering.API.Application.Commands
{
// Regular CommandHandler
public class SetStockRejectedOrderStatusCommandHandler : IRequestHandler<SetStockRejectedOrderStatusCommand, bool>
{
private readonly IOrderRepository _orderRepository;
public SetStockRejectedOrderStatusCommandHandler(IOrderRepository orderRepository)
{
_orderRepository = orderRepository;
}
/// <summary>
/// Handler which processes the command when
/// Stock service rejects the request
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
public async Task<bool> Handle(SetStockRejectedOrderStatusCommand command, CancellationToken cancellationToken)
{
// Simulate a work time for rejecting the stock
await Task.Delay(10000);
var orderToUpdate = await _orderRepository.GetAsync(command.OrderNumber);
if(orderToUpdate == null)
{
return false;
}
orderToUpdate.SetCancelledStatusWhenStockIsRejected(command.OrderStockItems);
return await _orderRepository.UnitOfWork.SaveEntitiesAsync();
}
}
// Use for Idempotency in Command process
public class SetStockRejectedOrderStatusIdenfifiedCommandHandler : IdentifiedCommandHandler<SetStockRejectedOrderStatusCommand, bool>
{
public SetStockRejectedOrderStatusIdenfifiedCommandHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
{
}
protected override bool CreateResultForDuplicateRequest()
{
return true; // Ignore duplicate requests for processing order.
}
}
}

View File

@ -1,5 +1,7 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -7,11 +9,11 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
public class GracePeriodConfirmedIntegrationEventHandler : IIntegrationEventHandler<GracePeriodConfirmedIntegrationEvent> public class GracePeriodConfirmedIntegrationEventHandler : IIntegrationEventHandler<GracePeriodConfirmedIntegrationEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IMediator _mediator;
public GracePeriodConfirmedIntegrationEventHandler(IOrderRepository orderRepository) public GracePeriodConfirmedIntegrationEventHandler(IMediator mediator)
{ {
_orderRepository = orderRepository; _mediator = mediator;
} }
/// <summary> /// <summary>
@ -24,9 +26,8 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
/// <returns></returns> /// <returns></returns>
public async Task Handle(GracePeriodConfirmedIntegrationEvent @event) public async Task Handle(GracePeriodConfirmedIntegrationEvent @event)
{ {
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId);
orderToUpdate.SetAwaitingValidationStatus(); await _mediator.Send(command);
await _orderRepository.UnitOfWork.SaveEntitiesAsync();
} }
} }
} }

View File

@ -1,27 +1,27 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
public class OrderPaymentFailedIntegrationEventHandler : public class OrderPaymentFailedIntegrationEventHandler :
IIntegrationEventHandler<OrderPaymentFailedIntegrationEvent> IIntegrationEventHandler<OrderPaymentFailedIntegrationEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IMediator _mediator;
public OrderPaymentFailedIntegrationEventHandler(IOrderRepository orderRepository) public OrderPaymentFailedIntegrationEventHandler(IMediator mediator)
{ {
_orderRepository = orderRepository; _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
} }
public async Task Handle(OrderPaymentFailedIntegrationEvent @event) public async Task Handle(OrderPaymentFailedIntegrationEvent @event)
{ {
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId); var command = new CancelOrderCommand(@event.OrderId);
await _mediator.Send(command);
orderToUpdate.SetCancelledStatus();
await _orderRepository.UnitOfWork.SaveEntitiesAsync();
} }
} }
} }

View File

@ -1,30 +1,27 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using System;
using System.Threading.Tasks; using System.Threading.Tasks;
public class OrderPaymentSuccededIntegrationEventHandler : public class OrderPaymentSuccededIntegrationEventHandler :
IIntegrationEventHandler<OrderPaymentSuccededIntegrationEvent> IIntegrationEventHandler<OrderPaymentSuccededIntegrationEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IMediator _mediator;
public OrderPaymentSuccededIntegrationEventHandler(IOrderRepository orderRepository) public OrderPaymentSuccededIntegrationEventHandler(IMediator mediator)
{ {
_orderRepository = orderRepository; _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
} }
public async Task Handle(OrderPaymentSuccededIntegrationEvent @event) public async Task Handle(OrderPaymentSuccededIntegrationEvent @event)
{ {
// Simulate a work time for validating the payment var command = new SetPaidOrderStatusCommand(@event.OrderId);
await Task.Delay(10000); await _mediator.Send(command);
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
orderToUpdate.SetPaidStatus();
await _orderRepository.UnitOfWork.SaveEntitiesAsync();
} }
} }
} }

View File

@ -4,27 +4,24 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Events; using Events;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using MediatR;
using System;
using Ordering.API.Application.Commands;
public class OrderStockConfirmedIntegrationEventHandler : public class OrderStockConfirmedIntegrationEventHandler :
IIntegrationEventHandler<OrderStockConfirmedIntegrationEvent> IIntegrationEventHandler<OrderStockConfirmedIntegrationEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IMediator _mediator;
public OrderStockConfirmedIntegrationEventHandler(IOrderRepository orderRepository) public OrderStockConfirmedIntegrationEventHandler(IMediator mediator)
{ {
_orderRepository = orderRepository; _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
} }
public async Task Handle(OrderStockConfirmedIntegrationEvent @event) public async Task Handle(OrderStockConfirmedIntegrationEvent @event)
{ {
// Simulate a work time for confirming the stock var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId);
await Task.Delay(10000); await _mediator.Send(command);
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
orderToUpdate.SetStockConfirmedStatus();
await _orderRepository.UnitOfWork.SaveEntitiesAsync();
} }
} }
} }

View File

@ -5,27 +5,27 @@
using Events; using Events;
using System.Linq; using System.Linq;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using MediatR;
using Ordering.API.Application.Commands;
public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler<OrderStockRejectedIntegrationEvent> public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler<OrderStockRejectedIntegrationEvent>
{ {
private readonly IOrderRepository _orderRepository; private readonly IMediator _mediator;
public OrderStockRejectedIntegrationEventHandler(IOrderRepository orderRepository) public OrderStockRejectedIntegrationEventHandler(IMediator mediator)
{ {
_orderRepository = orderRepository; _mediator = mediator;
} }
public async Task Handle(OrderStockRejectedIntegrationEvent @event) public async Task Handle(OrderStockRejectedIntegrationEvent @event)
{ {
var orderToUpdate = await _orderRepository.GetAsync(@event.OrderId);
var orderStockRejectedItems = @event.OrderStockItems var orderStockRejectedItems = @event.OrderStockItems
.FindAll(c => !c.HasStock) .FindAll(c => !c.HasStock)
.Select(c => c.ProductId); .Select(c => c.ProductId)
.ToList();
orderToUpdate.SetCancelledStatusWhenStockIsRejected(orderStockRejectedItems); var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems);
await _mediator.Send(command);
await _orderRepository.UnitOfWork.SaveEntitiesAsync();
} }
} }
} }