From ea5c65b4f82a459a403a4e7de5e2c3acdfb91c90 Mon Sep 17 00:00:00 2001 From: Christian Arenas Date: Mon, 15 May 2017 19:05:47 +0200 Subject: [PATCH] Add OrderStockConfirmed and ProductPriceChanged IntegrationEvent --- .../ConfirmOrderStockCommandMsgHandler.cs} | 15 +++---- .../DecrementOrderStockCommandMsgHandler.cs | 42 +++++++++++++++++++ .../Commands/ConfirmOrderStockCommandMsg.cs} | 6 +-- .../Commands/DecrementOrderStockCommandMsg.cs | 18 ++++++++ .../OrderStockConfirmedIntegrationEvent.cs | 2 +- .../ProductPriceChangedIntegrationEvent.cs | 11 ++--- src/Services/Catalog/Catalog.API/Startup.cs | 17 +++++++- 7 files changed, 90 insertions(+), 21 deletions(-) rename src/Services/Catalog/Catalog.API/{IntegrationEvents/EventHandling/ConfirmOrderStockIntegrationEventHandler.cs => IntegrationCommands/CommandHandlers/ConfirmOrderStockCommandMsgHandler.cs} (77%) create mode 100644 src/Services/Catalog/Catalog.API/IntegrationCommands/CommandHandlers/DecrementOrderStockCommandMsgHandler.cs rename src/Services/Catalog/Catalog.API/{IntegrationEvents/Events/ConfirmOrderStockIntegrationEvent.cs => IntegrationCommands/Commands/ConfirmOrderStockCommandMsg.cs} (81%) create mode 100644 src/Services/Catalog/Catalog.API/IntegrationCommands/Commands/DecrementOrderStockCommandMsg.cs diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/ConfirmOrderStockIntegrationEventHandler.cs b/src/Services/Catalog/Catalog.API/IntegrationCommands/CommandHandlers/ConfirmOrderStockCommandMsgHandler.cs similarity index 77% rename from src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/ConfirmOrderStockIntegrationEventHandler.cs rename to src/Services/Catalog/Catalog.API/IntegrationCommands/CommandHandlers/ConfirmOrderStockCommandMsgHandler.cs index 21d12e1ee..beb23bbaf 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/EventHandling/ConfirmOrderStockIntegrationEventHandler.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationCommands/CommandHandlers/ConfirmOrderStockCommandMsgHandler.cs @@ -1,4 +1,4 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.EventHandling +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.CommandHandlers { using BuildingBlocks.EventBus.Abstractions; using System.Threading.Tasks; @@ -9,21 +9,22 @@ using global::Catalog.API.Infrastructure.Exceptions; using global::Catalog.API.IntegrationEvents; using Model; - using Events; + using Commands; + using IntegrationEvents.Events; - public class ConfirmOrderStockIntegrationEventHandler : IIntegrationEventHandler + public class ConfirmOrderStockCommandMsgHandler : IIntegrationEventHandler { private readonly CatalogContext _catalogContext; private readonly ICatalogIntegrationEventService _catalogIntegrationEventService; - public ConfirmOrderStockIntegrationEventHandler(CatalogContext catalogContext, + public ConfirmOrderStockCommandMsgHandler(CatalogContext catalogContext, ICatalogIntegrationEventService catalogIntegrationEventService) { _catalogContext = catalogContext; _catalogIntegrationEventService = catalogIntegrationEventService; } - public async Task Handle(ConfirmOrderStockIntegrationEvent @event) + public async Task Handle(ConfirmOrderStockCommandMsg @event) { var confirmedOrderStockItems = new List(); @@ -38,15 +39,11 @@ confirmedOrderStockItems.Add(confirmedOrderStockItem); } - //Create Integration Event to be published through the Event Bus var confirmedIntegrationEvent = confirmedOrderStockItems.Any(c => !c.Confirmed) ? (IntegrationEvent) new OrderStockNotConfirmedIntegrationEvent(@event.OrderId, confirmedOrderStockItems) : new OrderStockConfirmedIntegrationEvent(@event.OrderId); - // Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transaction await _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(confirmedIntegrationEvent); - - // Publish through the Event Bus and mark the saved event as published await _catalogIntegrationEventService.PublishThroughEventBusAsync(confirmedIntegrationEvent); } diff --git a/src/Services/Catalog/Catalog.API/IntegrationCommands/CommandHandlers/DecrementOrderStockCommandMsgHandler.cs b/src/Services/Catalog/Catalog.API/IntegrationCommands/CommandHandlers/DecrementOrderStockCommandMsgHandler.cs new file mode 100644 index 000000000..962f5222d --- /dev/null +++ b/src/Services/Catalog/Catalog.API/IntegrationCommands/CommandHandlers/DecrementOrderStockCommandMsgHandler.cs @@ -0,0 +1,42 @@ +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.CommandHandlers +{ + using BuildingBlocks.EventBus.Abstractions; + using System.Threading.Tasks; + using Infrastructure; + using global::Catalog.API.Infrastructure.Exceptions; + using global::Catalog.API.IntegrationEvents; + using Model; + using Commands; + + public class DecrementOrderStockCommandMsgHandler : IIntegrationEventHandler + { + private readonly CatalogContext _catalogContext; + + public DecrementOrderStockCommandMsgHandler(CatalogContext catalogContext) + { + _catalogContext = catalogContext; + } + + public async Task Handle(DecrementOrderStockCommandMsg @event) + { + //we're not blocking stock/inventory + foreach (var orderStockItem in @event.OrderStockItems) + { + var catalogItem = _catalogContext.CatalogItems.Find(orderStockItem.ProductId); + CheckValidcatalogItemId(catalogItem); + + catalogItem.RemoveStock(orderStockItem.Units); + } + + await _catalogContext.SaveChangesAsync(); + } + + private void CheckValidcatalogItemId(CatalogItem catalogItem) + { + if (catalogItem is null) + { + throw new CatalogDomainException("Not able to process catalog event. Reason: no valid catalogItemId"); + } + } + } +} \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ConfirmOrderStockIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationCommands/Commands/ConfirmOrderStockCommandMsg.cs similarity index 81% rename from src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ConfirmOrderStockIntegrationEvent.cs rename to src/Services/Catalog/Catalog.API/IntegrationCommands/Commands/ConfirmOrderStockCommandMsg.cs index 366c8f854..f5fc805b2 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ConfirmOrderStockIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationCommands/Commands/ConfirmOrderStockCommandMsg.cs @@ -1,14 +1,14 @@ -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.Commands { using BuildingBlocks.EventBus.Events; using System.Collections.Generic; - public class ConfirmOrderStockIntegrationEvent : IntegrationEvent + public class ConfirmOrderStockCommandMsg : IntegrationEvent { public int OrderId { get; } public IEnumerable OrderStockItems { get; } - public ConfirmOrderStockIntegrationEvent(int orderId, + public ConfirmOrderStockCommandMsg(int orderId, IEnumerable orderStockItems) { OrderId = orderId; diff --git a/src/Services/Catalog/Catalog.API/IntegrationCommands/Commands/DecrementOrderStockCommandMsg.cs b/src/Services/Catalog/Catalog.API/IntegrationCommands/Commands/DecrementOrderStockCommandMsg.cs new file mode 100644 index 000000000..94bab1aa6 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/IntegrationCommands/Commands/DecrementOrderStockCommandMsg.cs @@ -0,0 +1,18 @@ +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.Commands +{ + using System.Collections.Generic; + using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + + public class DecrementOrderStockCommandMsg : IntegrationEvent + { + public int OrderId { get; } + public IEnumerable OrderStockItems { get; } + + public DecrementOrderStockCommandMsg(int orderId, + IEnumerable orderStockItems) + { + OrderId = orderId; + OrderStockItems = orderStockItems; + } + } +} \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs index 1ce179c3a..b91eaae43 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/OrderStockConfirmedIntegrationEvent.cs @@ -1,6 +1,6 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events { - using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; + using BuildingBlocks.EventBus.Events; public class OrderStockConfirmedIntegrationEvent : IntegrationEvent { diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs index 10b8317da..7c14a07d1 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/Events/ProductPriceChangedIntegrationEvent.cs @@ -1,10 +1,7 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; -using System; -using System.Collections.Generic; -using System.Text; - -namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events +namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Events { + using BuildingBlocks.EventBus.Events; + // Integration Events notes: // 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. @@ -23,4 +20,4 @@ namespace Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents.Eve OldPrice = oldPrice; } } -} +} \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Startup.cs b/src/Services/Catalog/Catalog.API/Startup.cs index 509048d4c..e224dea0a 100644 --- a/src/Services/Catalog/Catalog.API/Startup.cs +++ b/src/Services/Catalog/Catalog.API/Startup.cs @@ -14,6 +14,9 @@ using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Services; using Microsoft.eShopOnContainers.Services.Catalog.API.Infrastructure; + using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.Commands; + using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationEvents; + using Microsoft.eShopOnContainers.Services.Catalog.API.IntegrationCommands.CommandsHandlers; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.HealthChecks; @@ -24,7 +27,7 @@ using System.Data.Common; using System.Data.SqlClient; using System.Reflection; - + public class Startup { public IConfigurationRoot Configuration { get; } @@ -120,6 +123,8 @@ services.AddSingleton(); services.AddSingleton(); + services.AddTransient, ConfirmOrderStockCommandMsgHandler>(); + services.AddTransient, DecrementOrderStockCommandMsgHandler>(); var container = new ContainerBuilder(); container.Populate(services); @@ -149,6 +154,8 @@ CatalogContextSeed.SeedAsync(app, loggerFactory) .Wait(); + ConfigureEventBus(app); + var integrationEventLogContext = new IntegrationEventLogContext( new DbContextOptionsBuilder() .UseSqlServer(Configuration["ConnectionString"], b => b.MigrationsAssembly("Catalog.API")) @@ -180,5 +187,13 @@ ctx.Database.CloseConnection(); } } + + private void ConfigureEventBus(IApplicationBuilder app) + { + var eventBus = app.ApplicationServices.GetRequiredService(); + + eventBus.Subscribe>(); + eventBus.Subscribe>(); + } } }