Moved Integrationevent to Application folder
Created basic structure for order process saga
This commit is contained in:
parent
2785dd7932
commit
3f3b9b09e9
@ -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 CancelOrderCommand : IAsyncRequest<bool>
|
||||
{
|
||||
|
||||
[DataMember]
|
||||
public int OrderNumber { get; private set; }
|
||||
|
||||
public CancelOrderCommand(int orderNumber)
|
||||
{
|
||||
OrderNumber = orderNumber;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ordering.API.Application.IntegrationCommands.Commands
|
||||
{
|
||||
public class ConfirmGracePeriodCommandMsg : IntegrationEvent
|
||||
{
|
||||
public int OrderNumber { get; private set; }
|
||||
|
||||
//TODO: message should change to Integration command type once command bus is implemented
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||
|
||||
namespace Ordering.API.Application.IntegrationCommands.Commands
|
||||
{
|
||||
public class SubmitOrderCommandMsg : IntegrationEvent
|
||||
{
|
||||
public int OrderNumber { get; private set; }
|
||||
//TODO: message should change to Integration command type once command bus is implemented
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ordering.API.IntegrationEvents.Events
|
||||
namespace Ordering.API.Application.IntegrationEvents.Events
|
||||
{
|
||||
// Integration Events notes:
|
||||
// An Event is “something that has happened in the past”, therefore its name has to be
|
@ -1,10 +1,7 @@
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ordering.API.IntegrationEvents
|
||||
namespace Ordering.API.Application.IntegrationEvents
|
||||
{
|
||||
public interface IOrderingIntegrationEventService
|
||||
{
|
@ -1,16 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ordering.API.IntegrationEvents
|
||||
namespace Ordering.API.Application.IntegrationEvents
|
||||
{
|
||||
public class OrderingIntegrationEventService : IOrderingIntegrationEventService
|
||||
{
|
||||
@ -19,7 +17,7 @@ namespace Ordering.API.IntegrationEvents
|
||||
private readonly OrderingContext _orderingContext;
|
||||
private readonly IIntegrationEventLogService _eventLogService;
|
||||
|
||||
public OrderingIntegrationEventService (IEventBus eventBus, OrderingContext orderingContext,
|
||||
public OrderingIntegrationEventService(IEventBus eventBus, OrderingContext orderingContext,
|
||||
Func<DbConnection, IIntegrationEventLogService> integrationEventLogServiceFactory)
|
||||
{
|
||||
_orderingContext = orderingContext ?? throw new ArgumentNullException(nameof(orderingContext));
|
@ -0,0 +1,126 @@
|
||||
using Autofac.Features.OwnedInstances;
|
||||
using MediatR;
|
||||
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
|
||||
using Ordering.API.Application.Commands;
|
||||
using Ordering.API.Application.IntegrationCommands.Commands;
|
||||
using Ordering.Domain.Exceptions;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ordering.API.Application.Sagas
|
||||
{
|
||||
/// <summary>
|
||||
/// Saga for handling the place order process
|
||||
/// and which is started once the basket.api has
|
||||
/// successfully processed the items ordered.
|
||||
/// Saga provides a period of grace to give the customer
|
||||
/// the opportunity to cancel the order before proceeding
|
||||
/// with the validations.
|
||||
/// </summary>
|
||||
public class OrderProcessSaga : Saga<Order>,
|
||||
IIntegrationEventHandler<SubmitOrderCommandMsg>,
|
||||
IIntegrationEventHandler<ConfirmGracePeriodCommandMsg>,
|
||||
IAsyncRequestHandler<CancelOrderCommand, bool>
|
||||
{
|
||||
private readonly IMediator _mediator;
|
||||
private readonly Func<Owned<OrderingContext>> _dbContextFactory;
|
||||
|
||||
public OrderProcessSaga(
|
||||
Func<Owned<OrderingContext>> dbContextFactory, OrderingContext orderingContext,
|
||||
IMediator mediator)
|
||||
: base(orderingContext)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command handler which starts the create order process
|
||||
/// and initializes the saga
|
||||
/// </summary>
|
||||
/// <param name="command">
|
||||
/// Integration command message which is sent by the
|
||||
/// basket.api once it has successfully process the
|
||||
/// order items.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public async Task Handle(SubmitOrderCommandMsg command)
|
||||
{
|
||||
var orderSaga = FindSagaById(command.OrderNumber);
|
||||
CheckValidSagaId(orderSaga);
|
||||
|
||||
// TODO: This handler should change to Integration command handler type once command bus is implemented
|
||||
|
||||
// TODO: Send createOrder Command
|
||||
|
||||
// TODO: Set saga timeout
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Command handler which confirms that the grace period
|
||||
/// has been completed and order has not been cancelled.
|
||||
/// If so, the process continues for validation.
|
||||
/// </summary>
|
||||
/// <param name="command">
|
||||
/// Integration command message which is sent by a saga
|
||||
/// scheduler which provides the sagas that its grace
|
||||
/// period has completed.
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public async Task Handle(ConfirmGracePeriodCommandMsg command)
|
||||
{
|
||||
var orderSaga = FindSagaById(command.OrderNumber);
|
||||
CheckValidSagaId(orderSaga);
|
||||
|
||||
// TODO: This handler should change to Integration command handler type once command bus is implemented
|
||||
|
||||
// TODO: If order status is not cancelled, change state to awaitingValidation and
|
||||
// send ConfirmOrderStockCommandMsg to Inventory api
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Handler which processes the command when
|
||||
/// customer executes cancel order from app
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> Handle(CancelOrderCommand command)
|
||||
{
|
||||
var orderSaga = FindSagaById(command.OrderNumber);
|
||||
CheckValidSagaId(orderSaga);
|
||||
|
||||
// Set order status tu cancelled
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CheckValidSagaId(Order orderSaga)
|
||||
{
|
||||
if (orderSaga is null)
|
||||
{
|
||||
throw new OrderingDomainException("Not able to process order saga event. Reason: no valid orderId");
|
||||
}
|
||||
}
|
||||
|
||||
#region CommandHandlerIdentifiers
|
||||
|
||||
public class CancelOrderCommandIdentifiedHandler : IdentifierCommandHandler<CancelOrderCommand, bool>
|
||||
{
|
||||
public CancelOrderCommandIdentifiedHandler(IMediator mediator, IRequestManager requestManager) : base(mediator, requestManager)
|
||||
{
|
||||
}
|
||||
|
||||
protected override bool CreateResultForDuplicateRequest()
|
||||
{
|
||||
return true; // Ignore duplicate requests for processing order.
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
30
src/Services/Ordering/Ordering.API/Application/Sagas/Saga.cs
Normal file
30
src/Services/Ordering/Ordering.API/Application/Sagas/Saga.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.eShopOnContainers.Services.Ordering.Domain.Seedwork;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ordering.API.Application.Sagas
|
||||
{
|
||||
public abstract class Saga<TEntity> where TEntity : Entity
|
||||
{
|
||||
private readonly DbContext _dbContext;
|
||||
|
||||
public Saga(DbContext dbContext)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
}
|
||||
|
||||
protected TEntity FindSagaById(int id, DbContext context = null)
|
||||
{
|
||||
var ctx = context ?? _dbContext;
|
||||
return ctx.Set<TEntity>().Where(x => x.Id == id).SingleOrDefault();
|
||||
}
|
||||
|
||||
protected async Task<bool> SaveChangesAsync(DbContext context = null)
|
||||
{
|
||||
var ctx = context ?? _dbContext;
|
||||
var result = await ctx.SaveChangesAsync();
|
||||
return result > 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -79,8 +79,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Application\IntegrationCommands\CommandHandlers\" />
|
||||
<Folder Include="Application\IntegrationEvents\EventHandling\" />
|
||||
<Folder Include="Infrastructure\IntegrationEventMigrations\" />
|
||||
<Folder Include="IntegrationEvents\EventHandling\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
Loading…
x
Reference in New Issue
Block a user