Refactor Ordering Api eventbus using CAP

This commit is contained in:
Savorboard 2019-03-14 11:59:57 +08:00
parent 244d46bd4a
commit cf44ba2fd8
38 changed files with 161 additions and 466 deletions

View File

@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; using Ordering.API.Extensions;
namespace Ordering.API.Application.Behaviors namespace Ordering.API.Application.Behaviors
{ {

View File

@ -1,13 +1,12 @@
using MediatR; using MediatR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.API.Application.IntegrationEvents;
using Serilog.Context; using Serilog.Context;
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ordering.API.Extensions;
namespace Ordering.API.Application.Behaviors namespace Ordering.API.Application.Behaviors
{ {
@ -15,14 +14,11 @@ namespace Ordering.API.Application.Behaviors
{ {
private readonly ILogger<TransactionBehaviour<TRequest, TResponse>> _logger; private readonly ILogger<TransactionBehaviour<TRequest, TResponse>> _logger;
private readonly OrderingContext _dbContext; private readonly OrderingContext _dbContext;
private readonly IOrderingIntegrationEventService _orderingIntegrationEventService;
public TransactionBehaviour(OrderingContext dbContext, public TransactionBehaviour(OrderingContext dbContext,
IOrderingIntegrationEventService orderingIntegrationEventService,
ILogger<TransactionBehaviour<TRequest, TResponse>> logger) ILogger<TransactionBehaviour<TRequest, TResponse>> logger)
{ {
_dbContext = dbContext ?? throw new ArgumentException(nameof(OrderingContext)); _dbContext = dbContext ?? throw new ArgumentException(nameof(OrderingContext));
_orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentException(nameof(orderingIntegrationEventService));
_logger = logger ?? throw new ArgumentException(nameof(ILogger)); _logger = logger ?? throw new ArgumentException(nameof(ILogger));
} }
@ -53,8 +49,6 @@ namespace Ordering.API.Application.Behaviors
await _dbContext.CommitTransactionAsync(transaction); await _dbContext.CommitTransactionAsync(transaction);
} }
await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync();
}); });
return response; return response;

View File

@ -5,7 +5,7 @@ using Ordering.Domain.Exceptions;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions; using Ordering.API.Extensions;
namespace Ordering.API.Application.Behaviors namespace Ordering.API.Application.Behaviors
{ {

View File

@ -1,5 +1,4 @@
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency; using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure.Idempotency;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.API.Application.Behaviors; using Ordering.API.Application.Behaviors;
@ -7,6 +6,7 @@ using Ordering.API.Application.Commands;
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ordering.API.Extensions;
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands namespace Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands
{ {

View File

@ -1,18 +1,16 @@
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.API; using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.API.Application.Behaviors; using Ordering.API.Application.Behaviors;
using Ordering.API.Application.Commands; using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using Serilog.Context; using Serilog.Context;
using System.Threading.Tasks; using System.Threading.Tasks;
using DotNetCore.CAP;
namespace Ordering.API.Application.IntegrationEvents.EventHandling namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
public class GracePeriodConfirmedIntegrationEventHandler : IIntegrationEventHandler<GracePeriodConfirmedIntegrationEvent> public class GracePeriodConfirmedIntegrationEventHandler : ICapSubscribe
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ILogger<GracePeriodConfirmedIntegrationEventHandler> _logger; private readonly ILogger<GracePeriodConfirmedIntegrationEventHandler> _logger;
@ -30,24 +28,15 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
/// has been completed and order will not initially be cancelled. /// has been completed and order will not initially be cancelled.
/// Therefore, the order process continues for validation. /// Therefore, the order process continues for validation.
/// </summary> /// </summary>
/// <param name="event"> //TODO: [CapSubscribe(nameof(GracePeriodConfirmedIntegrationEvent))]
/// </param>
/// <returns></returns>
public async Task Handle(GracePeriodConfirmedIntegrationEvent @event) public async Task Handle(GracePeriodConfirmedIntegrationEvent @event)
{ {
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) using (LogContext.PushProperty("IntegrationEventContext", $"{Program.AppName}"))
{ {
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); _logger.LogInformation("----- Handling integration event: {AppName} - ({@IntegrationEvent})", Program.AppName, @event);
var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId); var command = new SetAwaitingValidationOrderStatusCommand(@event.OrderId);
_logger.LogInformation(
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
command.GetGenericTypeName(),
nameof(command.OrderNumber),
command.OrderNumber,
command);
await _mediator.Send(command); await _mediator.Send(command);
} }
} }

View File

@ -1,20 +1,17 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling using DotNetCore.CAP;
namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.API; using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.API.Application.Behaviors;
using Ordering.API.Application.Commands; using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using Serilog.Context; using Serilog.Context;
using System.Threading.Tasks; using System.Threading.Tasks;
using System; using System;
public class OrderPaymentFailedIntegrationEventHandler : public class OrderPaymentFailedIntegrationEventHandler : ICapSubscribe
IIntegrationEventHandler<OrderPaymentFailedIntegrationEvent>
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ILogger<OrderPaymentFailedIntegrationEventHandler> _logger; private readonly ILogger<OrderPaymentFailedIntegrationEventHandler> _logger;
@ -27,21 +24,15 @@
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
} }
//TODO: [CapSubscribe(nameof(OrderPaymentFailedIntegrationEvent))]
public async Task Handle(OrderPaymentFailedIntegrationEvent @event) public async Task Handle(OrderPaymentFailedIntegrationEvent @event)
{ {
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) using (LogContext.PushProperty("IntegrationEventContext", $"{Program.AppName}"))
{ {
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); _logger.LogInformation("----- Handling integration event: {AppName} - ({@IntegrationEvent})", Program.AppName, @event);
var command = new CancelOrderCommand(@event.OrderId); var command = new CancelOrderCommand(@event.OrderId);
_logger.LogInformation(
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
command.GetGenericTypeName(),
nameof(command.OrderNumber),
command.OrderNumber,
command);
await _mediator.Send(command); await _mediator.Send(command);
} }
} }

View File

@ -1,20 +1,17 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling using DotNetCore.CAP;
namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.API; using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.API.Application.Behaviors;
using Ordering.API.Application.Commands; using Ordering.API.Application.Commands;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using Serilog.Context; using Serilog.Context;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
public class OrderPaymentSuccededIntegrationEventHandler : public class OrderPaymentSuccededIntegrationEventHandler : ICapSubscribe
IIntegrationEventHandler<OrderPaymentSuccededIntegrationEvent>
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ILogger<OrderPaymentSuccededIntegrationEventHandler> _logger; private readonly ILogger<OrderPaymentSuccededIntegrationEventHandler> _logger;
@ -27,21 +24,15 @@
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
} }
//TODO: [CapSubscribe(nameof(OrderPaymentSuccededIntegrationEvent))]
public async Task Handle(OrderPaymentSuccededIntegrationEvent @event) public async Task Handle(OrderPaymentSuccededIntegrationEvent @event)
{ {
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) using (LogContext.PushProperty("IntegrationEventContext", $"{Program.AppName}"))
{ {
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); _logger.LogInformation("----- Handling integration event: {AppName} - ({@IntegrationEvent})", Program.AppName, @event);
var command = new SetPaidOrderStatusCommand(@event.OrderId); var command = new SetPaidOrderStatusCommand(@event.OrderId);
_logger.LogInformation(
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
command.GetGenericTypeName(),
nameof(command.OrderNumber),
command.OrderNumber,
command);
await _mediator.Send(command); await _mediator.Send(command);
} }
} }

View File

@ -1,20 +1,17 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling using DotNetCore.CAP;
namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Events; using Events;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using MediatR; using MediatR;
using System; using System;
using Ordering.API.Application.Commands; using Ordering.API.Application.Commands;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Serilog.Context; using Serilog.Context;
using Microsoft.eShopOnContainers.Services.Ordering.API; using Microsoft.eShopOnContainers.Services.Ordering.API;
using Ordering.API.Application.Behaviors;
public class OrderStockConfirmedIntegrationEventHandler : public class OrderStockConfirmedIntegrationEventHandler :ICapSubscribe
IIntegrationEventHandler<OrderStockConfirmedIntegrationEvent>
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ILogger<OrderStockConfirmedIntegrationEventHandler> _logger; private readonly ILogger<OrderStockConfirmedIntegrationEventHandler> _logger;
@ -27,21 +24,15 @@
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
} }
//TODO: [CapSubscribe(nameof(OrderStockConfirmedIntegrationEvent))]
public async Task Handle(OrderStockConfirmedIntegrationEvent @event) public async Task Handle(OrderStockConfirmedIntegrationEvent @event)
{ {
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) using (LogContext.PushProperty("IntegrationEventContext", $"{Program.AppName}"))
{ {
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); _logger.LogInformation("----- Handling integration event: {AppName} - ({@IntegrationEvent})", Program.AppName, @event);
var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId); var command = new SetStockConfirmedOrderStatusCommand(@event.OrderId);
_logger.LogInformation(
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
command.GetGenericTypeName(),
nameof(command.OrderNumber),
command.OrderNumber,
command);
await _mediator.Send(command); await _mediator.Send(command);
} }
} }

View File

@ -1,19 +1,17 @@
namespace Ordering.API.Application.IntegrationEvents.EventHandling using DotNetCore.CAP;
namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Events; using Events;
using System.Linq; using System.Linq;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.OrderAggregate;
using MediatR; using MediatR;
using Ordering.API.Application.Commands; using Ordering.API.Application.Commands;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Serilog.Context; using Serilog.Context;
using Microsoft.eShopOnContainers.Services.Ordering.API; using Microsoft.eShopOnContainers.Services.Ordering.API;
using Ordering.API.Application.Behaviors;
public class OrderStockRejectedIntegrationEventHandler : IIntegrationEventHandler<OrderStockRejectedIntegrationEvent> public class OrderStockRejectedIntegrationEventHandler :ICapSubscribe
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ILogger<OrderStockRejectedIntegrationEventHandler> _logger; private readonly ILogger<OrderStockRejectedIntegrationEventHandler> _logger;
@ -26,11 +24,12 @@
_logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); _logger = logger ?? throw new System.ArgumentNullException(nameof(logger));
} }
//TODO: [CapSubscribe(nameof(OrderStockRejectedIntegrationEvent))]
public async Task Handle(OrderStockRejectedIntegrationEvent @event) public async Task Handle(OrderStockRejectedIntegrationEvent @event)
{ {
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) using (LogContext.PushProperty("IntegrationEventContext", $"{Program.AppName}"))
{ {
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); _logger.LogInformation("----- Handling integration event: {AppName} - ({@IntegrationEvent})", Program.AppName, @event);
var orderStockRejectedItems = @event.OrderStockItems var orderStockRejectedItems = @event.OrderStockItems
.FindAll(c => !c.HasStock) .FindAll(c => !c.HasStock)
@ -39,13 +38,6 @@
var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems); var command = new SetStockRejectedOrderStatusCommand(@event.OrderId, orderStockRejectedItems);
_logger.LogInformation(
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
command.GetGenericTypeName(),
nameof(command.OrderNumber),
command.OrderNumber,
command);
await _mediator.Send(command); await _mediator.Send(command);
} }
} }

View File

@ -1,18 +1,16 @@
using MediatR; using MediatR;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API; using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ordering.API.Application.Behaviors;
using Ordering.API.Application.IntegrationEvents.Events; using Ordering.API.Application.IntegrationEvents.Events;
using Serilog.Context; using Serilog.Context;
using System.Threading.Tasks; using System.Threading.Tasks;
using System; using System;
using DotNetCore.CAP;
namespace Ordering.API.Application.IntegrationEvents.EventHandling namespace Ordering.API.Application.IntegrationEvents.EventHandling
{ {
public class UserCheckoutAcceptedIntegrationEventHandler : IIntegrationEventHandler<UserCheckoutAcceptedIntegrationEvent> public class UserCheckoutAcceptedIntegrationEventHandler : ICapSubscribe
{ {
private readonly IMediator _mediator; private readonly IMediator _mediator;
private readonly ILogger<UserCheckoutAcceptedIntegrationEventHandler> _logger; private readonly ILogger<UserCheckoutAcceptedIntegrationEventHandler> _logger;
@ -33,12 +31,12 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
/// basket.api once it has successfully process the /// basket.api once it has successfully process the
/// order items. /// order items.
/// </param> /// </param>
/// <returns></returns> //TODO: [CapSubscribe(nameof(UserCheckoutAcceptedIntegrationEvent))]
public async Task Handle(UserCheckoutAcceptedIntegrationEvent @event) public async Task Handle(UserCheckoutAcceptedIntegrationEvent @event)
{ {
using (LogContext.PushProperty("IntegrationEventContext", $"{@event.Id}-{Program.AppName}")) using (LogContext.PushProperty("IntegrationEventContext", $"{Program.AppName}"))
{ {
_logger.LogInformation("----- Handling integration event: {IntegrationEventId} at {AppName} - ({@IntegrationEvent})", @event.Id, Program.AppName, @event); _logger.LogInformation("----- Handling integration event: {AppName} - ({@IntegrationEvent})", Program.AppName, @event);
var result = false; var result = false;
@ -53,13 +51,6 @@ namespace Ordering.API.Application.IntegrationEvents.EventHandling
var requestCreateOrder = new IdentifiedCommand<CreateOrderCommand, bool>(createOrderCommand, @event.RequestId); var requestCreateOrder = new IdentifiedCommand<CreateOrderCommand, bool>(createOrderCommand, @event.RequestId);
_logger.LogInformation(
"----- Sending command: {CommandName} - {IdProperty}: {CommandId} ({@Command})",
requestCreateOrder.GetGenericTypeName(),
nameof(requestCreateOrder.Id),
requestCreateOrder.Id,
requestCreateOrder);
result = await _mediator.Send(requestCreateOrder); result = await _mediator.Send(requestCreateOrder);
if (result) if (result)

View File

@ -1,8 +1,6 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; public class GracePeriodConfirmedIntegrationEvent
public class GracePeriodConfirmedIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }

View File

@ -1,8 +1,6 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; public class OrderPaymentFailedIntegrationEvent
public class OrderPaymentFailedIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }

View File

@ -1,8 +1,6 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; public class OrderPaymentSuccededIntegrationEvent
public class OrderPaymentSuccededIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }

View File

@ -1,15 +1,9 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; namespace Ordering.API.Application.IntegrationEvents.Events
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.Events
{ {
// Integration Events notes: // Integration Events notes:
// An Event is “something that has happened in the past”, therefore its name has to be // An Event is “something that has happened in the past”, therefore its name has to be
// An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems. // An Integration Event is an event that can cause side effects to other microsrvices, Bounded-Contexts or external systems.
public class OrderStartedIntegrationEvent : IntegrationEvent public class OrderStartedIntegrationEvent
{ {
public string UserId { get; set; } public string UserId { get; set; }

View File

@ -1,9 +1,8 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
public class OrderStatusChangedToAwaitingValidationIntegrationEvent : IntegrationEvent public class OrderStatusChangedToAwaitingValidationIntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; } public string OrderStatus { get; }

View File

@ -1,12 +1,6 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; namespace Ordering.API.Application.IntegrationEvents.Events
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.Events
{ {
public class OrderStatusChangedToCancelledIntegrationEvent : IntegrationEvent public class OrderStatusChangedToCancelledIntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; } public string OrderStatus { get; }

View File

@ -1,9 +1,8 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
public class OrderStatusChangedToPaidIntegrationEvent : IntegrationEvent public class OrderStatusChangedToPaidIntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; } public string OrderStatus { get; }

View File

@ -1,12 +1,6 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; namespace Ordering.API.Application.IntegrationEvents.Events
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.Events
{ {
public class OrderStatusChangedToShippedIntegrationEvent : IntegrationEvent public class OrderStatusChangedToShippedIntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; } public string OrderStatus { get; }

View File

@ -1,8 +1,6 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; public class OrderStatusChangedToStockConfirmedIntegrationEvent
public class OrderStatusChangedToStockConfirmedIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; } public string OrderStatus { get; }

View File

@ -1,12 +1,6 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; namespace Ordering.API.Application.IntegrationEvents.Events
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents.Events
{ {
public class OrderStatusChangedToSubmittedIntegrationEvent : IntegrationEvent public class OrderStatusChangedToSubmittedIntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }
public string OrderStatus { get; } public string OrderStatus { get; }

View File

@ -1,8 +1,6 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; public class OrderStockConfirmedIntegrationEvent
public class OrderStockConfirmedIntegrationEvent : IntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }

View File

@ -1,9 +1,8 @@
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using System.Collections.Generic; using System.Collections.Generic;
public class OrderStockRejectedIntegrationEvent : IntegrationEvent public class OrderStockRejectedIntegrationEvent
{ {
public int OrderId { get; } public int OrderId { get; }

View File

@ -1,10 +1,9 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using Ordering.API.Application.Models;
using Ordering.API.Application.Models;
using System; using System;
namespace Ordering.API.Application.IntegrationEvents.Events namespace Ordering.API.Application.IntegrationEvents.Events
{ {
public class UserCheckoutAcceptedIntegrationEvent : IntegrationEvent public class UserCheckoutAcceptedIntegrationEvent
{ {
public string UserId { get; } public string UserId { get; }

View File

@ -1,11 +1,9 @@
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using System.Threading.Tasks;
using System.Threading.Tasks;
namespace Ordering.API.Application.IntegrationEvents namespace Ordering.API.Application.IntegrationEvents
{ {
public interface IOrderingIntegrationEventService public interface IOrderingIntegrationEventService
{ {
Task PublishEventsThroughEventBusAsync(); Task AddAndSaveEventAsync(object evt);
Task AddAndSaveEventAsync(IntegrationEvent evt);
} }
} }

View File

@ -1,72 +1,34 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Utilities;
using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System; using System;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using DotNetCore.CAP;
using Ordering.API.Extensions;
namespace Ordering.API.Application.IntegrationEvents namespace Ordering.API.Application.IntegrationEvents
{ {
public class OrderingIntegrationEventService : IOrderingIntegrationEventService public class OrderingIntegrationEventService : IOrderingIntegrationEventService
{ {
private readonly Func<DbConnection, IIntegrationEventLogService> _integrationEventLogServiceFactory; private readonly ICapPublisher _eventBus;
private readonly IEventBus _eventBus;
private readonly OrderingContext _orderingContext; private readonly OrderingContext _orderingContext;
private readonly IntegrationEventLogContext _eventLogContext;
private readonly IIntegrationEventLogService _eventLogService;
private readonly ILogger<OrderingIntegrationEventService> _logger; private readonly ILogger<OrderingIntegrationEventService> _logger;
public OrderingIntegrationEventService(IEventBus eventBus, public OrderingIntegrationEventService(ICapPublisher eventBus,
OrderingContext orderingContext, OrderingContext orderingContext,
IntegrationEventLogContext eventLogContext,
Func<DbConnection, IIntegrationEventLogService> integrationEventLogServiceFactory,
ILogger<OrderingIntegrationEventService> logger) ILogger<OrderingIntegrationEventService> logger)
{ {
_orderingContext = orderingContext ?? throw new ArgumentNullException(nameof(orderingContext)); _orderingContext = orderingContext ?? throw new ArgumentNullException(nameof(orderingContext));
_eventLogContext = eventLogContext ?? throw new ArgumentNullException(nameof(eventLogContext));
_integrationEventLogServiceFactory = integrationEventLogServiceFactory ?? throw new ArgumentNullException(nameof(integrationEventLogServiceFactory));
_eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus)); _eventBus = eventBus ?? throw new ArgumentNullException(nameof(eventBus));
_eventLogService = _integrationEventLogServiceFactory(_orderingContext.Database.GetDbConnection());
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
} }
public async Task PublishEventsThroughEventBusAsync() public async Task AddAndSaveEventAsync(object evt)
{ {
var pendindLogEvents = await _eventLogService.RetrieveEventLogsPendingToPublishAsync(); _logger.LogInformation("----- Enqueuing integration event to repository ({@IntegrationEvent})", evt);
foreach (var logEvt in pendindLogEvents) _eventBus.Transaction.Begin(_orderingContext.GetCurrentTransaction.GetDbTransaction());
{ await _eventBus.PublishAsync(evt.GetGenericTypeName(), evt);
_logger.LogInformation("----- Publishing integration event: {IntegrationEventId} from {AppName} - ({@IntegrationEvent})", logEvt.EventId, Program.AppName, logEvt.IntegrationEvent);
try
{
await _eventLogService.MarkEventAsInProgressAsync(logEvt.EventId);
_eventBus.Publish(logEvt.IntegrationEvent);
await _eventLogService.MarkEventAsPublishedAsync(logEvt.EventId);
}
catch (Exception ex)
{
_logger.LogError(ex, "ERROR publishing integration event: {IntegrationEventId} from {AppName}", logEvt.EventId, Program.AppName);
await _eventLogService.MarkEventAsFailedAsync(logEvt.EventId);
}
}
}
public async Task AddAndSaveEventAsync(IntegrationEvent evt)
{
_logger.LogInformation("----- Enqueuing integration event {IntegrationEventId} to repository ({@IntegrationEvent})", evt.Id, evt);
await _eventLogService.SaveEventAsync(evt, _orderingContext.GetCurrentTransaction.GetDbTransaction());
} }
} }
} }

View File

@ -1,7 +1,6 @@
using MediatR; using MediatR;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Extensions;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Services;
@ -12,6 +11,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ordering.API.Extensions;
namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers namespace Microsoft.eShopOnContainers.Services.Ordering.API.Controllers
{ {

View File

@ -0,0 +1,30 @@
using System;
using System.Linq;
namespace Ordering.API.Extensions
{
public static class GenericTypeExtensions
{
public static string GetGenericTypeName(this Type type)
{
var typeName = string.Empty;
if (type.IsGenericType)
{
var genericTypes = string.Join(",", type.GetGenericArguments().Select(t => t.Name).ToArray());
typeName = $"{type.Name.Remove(type.Name.IndexOf('`'))}<{genericTypes}>";
}
else
{
typeName = type.Name;
}
return typeName;
}
public static string GetGenericTypeName(this object @object)
{
return @object.GetType().GetGenericTypeName();
}
}
}

View File

@ -1,5 +1,4 @@
using Autofac; using Autofac;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Commands;
using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries; using Microsoft.eShopOnContainers.Services.Ordering.API.Application.Queries;
using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate; using Microsoft.eShopOnContainers.Services.Ordering.Domain.AggregatesModel.BuyerAggregate;
@ -42,8 +41,8 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure.Autof
.As<IRequestManager>() .As<IRequestManager>()
.InstancePerLifetimeScope(); .InstancePerLifetimeScope();
builder.RegisterAssemblyTypes(typeof(CreateOrderCommandHandler).GetTypeInfo().Assembly) //builder.RegisterAssemblyTypes(typeof(CreateOrderCommandHandler).GetTypeInfo().Assembly)
.AsClosedTypesOf(typeof(IIntegrationEventHandler<>)); // .AsClosedTypesOf(typeof(IIntegrationEventHandler<>));
} }
} }

View File

@ -1,43 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
namespace Ordering.API.Infrastructure.IntegrationEventMigrations
{
[DbContext(typeof(IntegrationEventLogContext))]
[Migration("20170330131634_IntegrationEventInitial")]
partial class IntegrationEventInitial
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.1.1")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b =>
{
b.Property<Guid>("EventId")
.ValueGeneratedOnAdd();
b.Property<string>("Content")
.IsRequired();
b.Property<DateTime>("CreationTime");
b.Property<string>("EventTypeName")
.IsRequired();
b.Property<int>("State");
b.Property<int>("TimesSent");
b.HasKey("EventId");
b.ToTable("IntegrationEventLog");
});
}
}
}

View File

@ -1,34 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace Ordering.API.Infrastructure.IntegrationEventMigrations
{
public partial class IntegrationEventInitial : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "IntegrationEventLog",
columns: table => new
{
EventId = table.Column<Guid>(nullable: false),
Content = table.Column<string>(nullable: false),
CreationTime = table.Column<DateTime>(nullable: false),
EventTypeName = table.Column<string>(nullable: false),
State = table.Column<int>(nullable: false),
TimesSent = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_IntegrationEventLog", x => x.EventId);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "IntegrationEventLog");
}
}
}

View File

@ -1,42 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
namespace Ordering.API.Infrastructure.IntegrationEventMigrations
{
[DbContext(typeof(IntegrationEventLogContext))]
partial class IntegrationEventLogContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
modelBuilder
.HasAnnotation("ProductVersion", "1.1.1")
.HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b =>
{
b.Property<Guid>("EventId")
.ValueGeneratedOnAdd();
b.Property<string>("Content")
.IsRequired();
b.Property<DateTime>("CreationTime");
b.Property<string>("EventTypeName")
.IsRequired();
b.Property<int>("State");
b.Property<int>("TimesSent");
b.HasKey("EventId");
b.ToTable("IntegrationEventLog");
});
}
}
}

View File

@ -18,10 +18,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusRabbitMQ\EventBusRabbitMQ.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBusServiceBus\EventBusServiceBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\EventBus\EventBus.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\EventBus\IntegrationEventLogEF\IntegrationEventLogEF.csproj" />
<ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" /> <ProjectReference Include="..\..\..\BuildingBlocks\WebHostCustomization\WebHost.Customization\WebHost.Customization.csproj" />
<ProjectReference Include="..\Ordering.Domain\Ordering.Domain.csproj" /> <ProjectReference Include="..\Ordering.Domain\Ordering.Domain.csproj" />
<ProjectReference Include="..\Ordering.Infrastructure\Ordering.Infrastructure.csproj" /> <ProjectReference Include="..\Ordering.Infrastructure\Ordering.Infrastructure.csproj" />
@ -33,7 +29,11 @@
<PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" /> <PackageReference Include="AspNetCore.HealthChecks.SqlServer" Version="2.2.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.2" /> <PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="2.2.2" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" /> <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="4.2.1" />
<PackageReference Include="Dapper" Version="1.50.7" /> <PackageReference Include="Dapper" Version="1.60.1" />
<PackageReference Include="DotNetCore.CAP" Version="2.5.0-preview-69210974" />
<PackageReference Include="DotNetCore.CAP.AzureServiceBus" Version="2.5.0-preview-69210974" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="2.5.0-preview-69210974" />
<PackageReference Include="DotNetCore.CAP.SQLServer" Version="2.5.0-preview-69210974" />
<PackageReference Include="FluentValidation.AspNetCore" Version="7.5.0" /> <PackageReference Include="FluentValidation.AspNetCore" Version="7.5.0" />
<PackageReference Include="MediatR" Version="5.1.0" /> <PackageReference Include="MediatR" Version="5.1.0" />
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="5.1.0" /> <PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="5.1.0" />

View File

@ -1,6 +1,5 @@
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
@ -39,8 +38,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.API
new OrderingContextSeed() new OrderingContextSeed()
.SeedAsync(context, env, settings, logger) .SeedAsync(context, env, settings, logger)
.Wait(); .Wait();
}) });
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
Log.Information("Starting web host ({ApplicationContext})...", AppName); Log.Information("Starting web host ({ApplicationContext})...", AppName);
host.Run(); host.Run();

View File

@ -1,10 +1,11 @@
namespace Microsoft.eShopOnContainers.Services.Ordering.API using Ordering.API.Application.IntegrationEvents.EventHandling;
namespace Microsoft.eShopOnContainers.Services.Ordering.API
{ {
using AspNetCore.Http; using AspNetCore.Http;
using Autofac; using Autofac;
using Autofac.Extensions.DependencyInjection; using Autofac.Extensions.DependencyInjection;
using global::Ordering.API.Application.IntegrationEvents; using global::Ordering.API.Application.IntegrationEvents;
using global::Ordering.API.Application.IntegrationEvents.Events;
using global::Ordering.API.Infrastructure.Filters; using global::Ordering.API.Infrastructure.Filters;
using global::Ordering.API.Infrastructure.Middlewares; using global::Ordering.API.Infrastructure.Middlewares;
using Infrastructure.AutofacModules; using Infrastructure.AutofacModules;
@ -14,16 +15,8 @@
using Microsoft.ApplicationInsights.ServiceFabric; using Microsoft.ApplicationInsights.ServiceFabric;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.ServiceBus;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Abstractions;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ;
using Microsoft.eShopOnContainers.BuildingBlocks.EventBusServiceBus;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -32,7 +25,6 @@
using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.Swagger;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Common;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Reflection; using System.Reflection;
using HealthChecks.UI.Client; using HealthChecks.UI.Client;
@ -57,6 +49,7 @@
.AddCustomSwagger(Configuration) .AddCustomSwagger(Configuration)
.AddCustomIntegrations(Configuration) .AddCustomIntegrations(Configuration)
.AddCustomConfiguration(Configuration) .AddCustomConfiguration(Configuration)
.AddIntegrationEventHandler()
.AddEventBus(Configuration) .AddEventBus(Configuration)
.AddCustomAuthentication(Configuration); .AddCustomAuthentication(Configuration);
@ -108,21 +101,6 @@
c.OAuthClientId("orderingswaggerui"); c.OAuthClientId("orderingswaggerui");
c.OAuthAppName("Ordering Swagger UI"); c.OAuthAppName("Ordering Swagger UI");
}); });
ConfigureEventBus(app);
}
private void ConfigureEventBus(IApplicationBuilder app)
{
var eventBus = app.ApplicationServices.GetRequiredService<BuildingBlocks.EventBus.Abstractions.IEventBus>();
eventBus.Subscribe<UserCheckoutAcceptedIntegrationEvent, IIntegrationEventHandler<UserCheckoutAcceptedIntegrationEvent>>();
eventBus.Subscribe<GracePeriodConfirmedIntegrationEvent, IIntegrationEventHandler<GracePeriodConfirmedIntegrationEvent>>();
eventBus.Subscribe<OrderStockConfirmedIntegrationEvent, IIntegrationEventHandler<OrderStockConfirmedIntegrationEvent>>();
eventBus.Subscribe<OrderStockRejectedIntegrationEvent, IIntegrationEventHandler<OrderStockRejectedIntegrationEvent>>();
eventBus.Subscribe<OrderPaymentFailedIntegrationEvent, IIntegrationEventHandler<OrderPaymentFailedIntegrationEvent>>();
eventBus.Subscribe<OrderPaymentSuccededIntegrationEvent, IIntegrationEventHandler<OrderPaymentSuccededIntegrationEvent>>();
} }
protected virtual void ConfigureAuth(IApplicationBuilder app) protected virtual void ConfigureAuth(IApplicationBuilder app)
@ -229,18 +207,6 @@
}, },
ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request) ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
); );
services.AddDbContext<IntegrationEventLogContext>(options =>
{
options.UseSqlServer(configuration["ConnectionString"],
sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name);
//Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
sqlOptions.EnableRetryOnFailure(maxRetryCount: 10, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);
});
});
return services; return services;
} }
@ -275,58 +241,25 @@
return services; return services;
} }
public static IServiceCollection AddIntegrationEventHandler(this IServiceCollection services)
{
services.AddTransient<GracePeriodConfirmedIntegrationEventHandler>();
services.AddTransient<OrderPaymentFailedIntegrationEventHandler>();
services.AddTransient<OrderPaymentSuccededIntegrationEventHandler>();
services.AddTransient<OrderStockConfirmedIntegrationEventHandler>();
services.AddTransient<OrderStockRejectedIntegrationEventHandler>();
services.AddTransient<UserCheckoutAcceptedIntegrationEventHandler>();
return services;
}
public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddCustomIntegrations(this IServiceCollection services, IConfiguration configuration)
{ {
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IIdentityService, IdentityService>(); services.AddTransient<IIdentityService, IdentityService>();
services.AddTransient<Func<DbConnection, IIntegrationEventLogService>>(
sp => (DbConnection c) => new IntegrationEventLogService(c));
services.AddTransient<IOrderingIntegrationEventService, OrderingIntegrationEventService>(); services.AddTransient<IOrderingIntegrationEventService, OrderingIntegrationEventService>();
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
{
services.AddSingleton<IServiceBusPersisterConnection>(sp =>
{
var logger = sp.GetRequiredService<ILogger<DefaultServiceBusPersisterConnection>>();
var serviceBusConnectionString = configuration["EventBusConnection"];
var serviceBusConnection = new ServiceBusConnectionStringBuilder(serviceBusConnectionString);
return new DefaultServiceBusPersisterConnection(serviceBusConnection, logger);
});
}
else
{
services.AddSingleton<IRabbitMQPersistentConnection>(sp =>
{
var logger = sp.GetRequiredService<ILogger<DefaultRabbitMQPersistentConnection>>();
var factory = new ConnectionFactory()
{
HostName = configuration["EventBusConnection"]
};
if (!string.IsNullOrEmpty(configuration["EventBusUserName"]))
{
factory.UserName = configuration["EventBusUserName"];
}
if (!string.IsNullOrEmpty(configuration["EventBusPassword"]))
{
factory.Password = configuration["EventBusPassword"];
}
var retryCount = 5;
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
{
retryCount = int.Parse(configuration["EventBusRetryCount"]);
}
return new DefaultRabbitMQPersistentConnection(factory, logger, retryCount);
});
}
return services; return services;
} }
@ -358,41 +291,40 @@
public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration) public static IServiceCollection AddEventBus(this IServiceCollection services, IConfiguration configuration)
{ {
var subscriptionClientName = configuration["SubscriptionClientName"]; services.AddCap(options =>
if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
{ {
services.AddSingleton<IEventBus, EventBusServiceBus>(sp => options.UseSqlServer(configuration["ConnectionString"]);
{
var serviceBusPersisterConnection = sp.GetRequiredService<IServiceBusPersisterConnection>();
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>();
var logger = sp.GetRequiredService<ILogger<EventBusServiceBus>>();
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>();
return new EventBusServiceBus(serviceBusPersisterConnection, logger, if (configuration.GetValue<bool>("AzureServiceBusEnabled"))
eventBusSubcriptionsManager, subscriptionClientName, iLifetimeScope);
});
}
else
{
services.AddSingleton<IEventBus, EventBusRabbitMQ>(sp =>
{ {
var rabbitMQPersistentConnection = sp.GetRequiredService<IRabbitMQPersistentConnection>(); options.UseAzureServiceBus(configuration["EventBusConnection"]);
var iLifetimeScope = sp.GetRequiredService<ILifetimeScope>(); }
var logger = sp.GetRequiredService<ILogger<EventBusRabbitMQ>>(); else
var eventBusSubcriptionsManager = sp.GetRequiredService<IEventBusSubscriptionsManager>(); {
options.UseRabbitMQ(conf =>
var retryCount = 5;
if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
{ {
retryCount = int.Parse(configuration["EventBusRetryCount"]); conf.HostName = configuration["EventBusConnection"];
} if (!string.IsNullOrEmpty(configuration["EventBusUserName"]))
{
conf.UserName = configuration["EventBusUserName"];
}
if (!string.IsNullOrEmpty(configuration["EventBusPassword"]))
{
conf.Password = configuration["EventBusPassword"];
}
});
}
return new EventBusRabbitMQ(rabbitMQPersistentConnection, logger, iLifetimeScope, eventBusSubcriptionsManager, subscriptionClientName, retryCount); if (!string.IsNullOrEmpty(configuration["EventBusRetryCount"]))
}); {
} options.FailedRetryCount = int.Parse(configuration["EventBusRetryCount"]);
}
services.AddSingleton<IEventBusSubscriptionsManager, InMemoryEventBusSubscriptionsManager>(); if (!string.IsNullOrEmpty(configuration["SubscriptionClientName"]))
{
options.DefaultGroup = configuration["SubscriptionClientName"];
}
});
return services; return services;
} }

View File

@ -12,7 +12,6 @@ using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
namespace Ordering.FunctionalTests namespace Ordering.FunctionalTests
{ {
@ -43,8 +42,7 @@ namespace Ordering.FunctionalTests
new OrderingContextSeed() new OrderingContextSeed()
.SeedAsync(context, env, settings, logger) .SeedAsync(context, env, settings, logger)
.Wait(); .Wait();
}) });
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
return testServer; return testServer;
} }

View File

@ -1,7 +1,6 @@
using Microsoft.AspNetCore; using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.Services.Catalog.API; using Microsoft.eShopOnContainers.Services.Catalog.API;
using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -40,8 +39,7 @@ namespace FunctionalTests.Services.Catalog
new CatalogContextSeed() new CatalogContextSeed()
.SeedAsync(context, env, settings, logger) .SeedAsync(context, env, settings, logger)
.Wait(); .Wait();
}) });
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
return testServer; return testServer;
} }

View File

@ -1,6 +1,5 @@
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost; using Microsoft.AspNetCore.TestHost;
using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF;
using Microsoft.eShopOnContainers.Services.Ordering.API; using Microsoft.eShopOnContainers.Services.Ordering.API;
using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.API.Infrastructure;
using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure; using Microsoft.eShopOnContainers.Services.Ordering.Infrastructure;
@ -40,8 +39,7 @@ namespace FunctionalTests.Services.Ordering
new OrderingContextSeed() new OrderingContextSeed()
.SeedAsync(context, env, settings, logger) .SeedAsync(context, env, settings, logger)
.Wait(); .Wait();
}) });
.MigrateDbContext<IntegrationEventLogContext>((_, __) => { });
return testServer; return testServer;
} }