Browse Source

Moved Integrationevent to Application folder

Created basic structure for order process saga
pull/809/head
Ramón Tomás 7 years ago
parent
commit
3f3b9b09e9
9 changed files with 212 additions and 10 deletions
  1. +21
    -0
      src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs
  2. +15
    -0
      src/Services/Ordering/Ordering.API/Application/IntegrationCommands/Commands/ConfirmGracePeriodCommandMsg.cs
  3. +14
    -0
      src/Services/Ordering/Ordering.API/Application/IntegrationCommands/Commands/SubmitOrderCommandMsg.cs
  4. +1
    -1
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs
  5. +1
    -4
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs
  6. +2
    -4
      src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs
  7. +126
    -0
      src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs
  8. +30
    -0
      src/Services/Ordering/Ordering.API/Application/Sagas/Saga.cs
  9. +2
    -1
      src/Services/Ordering/Ordering.API/Ordering.API.csproj

+ 21
- 0
src/Services/Ordering/Ordering.API/Application/Commands/CancelOrderCommand.cs 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 CancelOrderCommand : IAsyncRequest<bool>
{
[DataMember]
public int OrderNumber { get; private set; }
public CancelOrderCommand(int orderNumber)
{
OrderNumber = orderNumber;
}
}
}

+ 15
- 0
src/Services/Ordering/Ordering.API/Application/IntegrationCommands/Commands/ConfirmGracePeriodCommandMsg.cs View File

@ -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
}
}

+ 14
- 0
src/Services/Ordering/Ordering.API/Application/IntegrationCommands/Commands/SubmitOrderCommandMsg.cs View File

@ -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
}
}

src/Services/Ordering/Ordering.API/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs → src/Services/Ordering/Ordering.API/Application/IntegrationEvents/Events/OrderStartedIntegrationEvent.cs View File

@ -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

src/Services/Ordering/Ordering.API/IntegrationEvents/IOrderingIntegrationEventService.cs → src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs View File

@ -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
{

src/Services/Ordering/Ordering.API/IntegrationEvents/OrderingIntegrationEventService.cs → src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs View File

@ -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));

+ 126
- 0
src/Services/Ordering/Ordering.API/Application/Sagas/OrderProcessSaga.cs View File

@ -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
- 0
src/Services/Ordering/Ordering.API/Application/Sagas/Saga.cs View 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;
}
}
}

+ 2
- 1
src/Services/Ordering/Ordering.API/Ordering.API.csproj View File

@ -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…
Cancel
Save