From 61ecfba05215c56e4c6cdddf1731d93a7fd1c11a Mon Sep 17 00:00:00 2001 From: Miguel Veloso Date: Tue, 7 May 2019 21:29:37 +0100 Subject: [PATCH] Add a TransactionId to IntegrationEventLogEntry to ensure that chained integration events are only published once from the correct transaction scope --- docker-compose.override.yml | 4 ++ scripts/restore-packages | 2 +- .../EventBusRabbitMQ/EventBusRabbitMQ.cs | 36 +++++++++---- .../IntegrationEventLogEntry.cs | 5 +- .../Services/IIntegrationEventLogService.cs | 7 +-- .../Services/IntegrationEventLogService.cs | 18 +++---- ...0190507184807_AddTransactionId.Designer.cs | 50 +++++++++++++++++++ .../20190507184807_AddTransactionId.cs | 22 ++++++++ ...grationEventLogContextDesignTimeFactory.cs | 18 +++++++ ...IntegrationEventLogContextModelSnapshot.cs | 12 +++-- .../CatalogIntegrationEventService.cs | 2 +- .../Behaviors/TransactionBehaviour.cs | 6 ++- .../IOrderingIntegrationEventService.cs | 3 +- .../OrderingIntegrationEventService.cs | 6 +-- ...0190507185219_AddTransactionId.Designer.cs | 50 +++++++++++++++++++ .../20190507185219_AddTransactionId.cs | 22 ++++++++ ...grationEventLogContextDesignTimeFactory.cs | 18 +++++++ ...IntegrationEventLogContextModelSnapshot.cs | 12 +++-- .../OrderingContext.cs | 2 +- ...ToStockConfirmedIntegrationEventHandler.cs | 2 + 20 files changed, 261 insertions(+), 36 deletions(-) create mode 100644 src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.Designer.cs create mode 100644 src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.cs create mode 100644 src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs create mode 100644 src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.Designer.cs create mode 100644 src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.cs create mode 100644 src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 578d96f45..9ac365d1e 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -110,6 +110,7 @@ services: - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} - UseLoadTest=${USE_LOADTEST:-False} + - Serilog__MinimumLevel__Override__Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ=Verbose ports: - "5102:80" # Important: In a production environment your should remove the external port (5102) kept here for microservice debugging purposes. # The API Gateway redirects and access through the internal port (80). @@ -130,6 +131,7 @@ services: - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} - UseLoadTest=${USE_LOADTEST:-False} + - Serilog__MinimumLevel__Override__Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ=Verbose ports: - "5111:80" @@ -168,6 +170,8 @@ services: - AzureServiceBusEnabled=False - ApplicationInsights__InstrumentationKey=${INSTRUMENTATION_KEY} - OrchestratorType=${ORCHESTRATOR_TYPE} + - Serilog__MinimumLevel__Override__Payment.API.IntegrationEvents.EventHandling=Verbose + - Serilog__MinimumLevel__Override__Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ=Verbose ports: - "5108:80" # Important: In a production environment your should remove the external port (5108) kept here for microservice debugging purposes. # The API Gateway redirects and access through the internal port (80). diff --git a/scripts/restore-packages b/scripts/restore-packages index 5ad4abf62..58bb10c62 100644 --- a/scripts/restore-packages +++ b/scripts/restore-packages @@ -1 +1 @@ -echo RESTORING ALL PACKAGES...; for f in /src/csproj-files/*.csproj; do dotnet restore $f; done +echo RESTORING ALL PACKAGES...; for f in /src/csproj-files/*.csproj; do dotnet restore $f; done \ No newline at end of file diff --git a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs index 397b75017..99c5b4bbf 100644 --- a/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs +++ b/src/BuildingBlocks/EventBus/EventBusRabbitMQ/EventBusRabbitMQ.cs @@ -80,13 +80,16 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ _logger.LogWarning(ex, "Could not publish event: {EventId} after {Timeout}s ({ExceptionMessage})", @event.Id, $"{time.TotalSeconds:n1}", ex.Message); }); + var eventName = @event.GetType().Name; + + _logger.LogTrace("Creating RabbitMQ channel to publish event: {EventId} ({EventName})", @event.Id, eventName); + using (var channel = _persistentConnection.CreateModel()) { - var eventName = @event.GetType() - .Name; - channel.ExchangeDeclare(exchange: BROKER_NAME, - type: "direct"); + _logger.LogTrace("Declaring RabbitMQ exchange to publish event: {EventId}", @event.Id); + + channel.ExchangeDeclare(exchange: BROKER_NAME, type: "direct"); var message = JsonConvert.SerializeObject(@event); var body = Encoding.UTF8.GetBytes(message); @@ -96,11 +99,14 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ var properties = channel.CreateBasicProperties(); properties.DeliveryMode = 2; // persistent - channel.BasicPublish(exchange: BROKER_NAME, - routingKey: eventName, - mandatory: true, - basicProperties: properties, - body: body); + _logger.LogTrace("Publishing event to RabbitMQ: {EventId}", @event.Id); + + channel.BasicPublish( + exchange: BROKER_NAME, + routingKey: eventName, + mandatory: true, + basicProperties: properties, + body: body); }); } } @@ -176,6 +182,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ private void StartBasicConsume() { + _logger.LogTrace("Starting RabbitMQ basic consume"); + if (_consumerChannel != null) { var consumer = new AsyncEventingBasicConsumer(_consumerChannel); @@ -225,6 +233,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ _persistentConnection.TryConnect(); } + _logger.LogTrace("Creating RabbitMQ consumer channel"); + var channel = _persistentConnection.CreateModel(); channel.ExchangeDeclare(exchange: BROKER_NAME, @@ -238,6 +248,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ channel.CallbackException += (sender, ea) => { + _logger.LogWarning(ea.Exception, "Recreating RabbitMQ consumer channel"); + _consumerChannel.Dispose(); _consumerChannel = CreateConsumerChannel(); StartBasicConsume(); @@ -248,6 +260,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ private async Task ProcessEvent(string eventName, string message) { + _logger.LogTrace("Processing RabbitMQ event: {EventName}", eventName); + if (_subsManager.HasSubscriptionsForEvent(eventName)) { using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME)) @@ -274,6 +288,10 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.EventBusRabbitMQ } } } + else + { + _logger.LogWarning("No subscription for RabbitMQ event: {EventName}", eventName); + } } } } diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs index e5c3bc9ad..dc65fa525 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/IntegrationEventLogEntry.cs @@ -12,7 +12,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF public class IntegrationEventLogEntry { private IntegrationEventLogEntry() { } - public IntegrationEventLogEntry(IntegrationEvent @event) + public IntegrationEventLogEntry(IntegrationEvent @event, Guid transactionId) { EventId = @event.Id; CreationTime = @event.CreationDate; @@ -20,7 +20,9 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF Content = JsonConvert.SerializeObject(@event); State = EventStateEnum.NotPublished; TimesSent = 0; + TransactionId = transactionId.ToString(); } + public Guid EventId { get; private set; } public string EventTypeName { get; private set; } [NotMapped] @@ -31,6 +33,7 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF public int TimesSent { get; set; } public DateTime CreationTime { get; private set; } public string Content { get; private set; } + public string TransactionId { get; private set; } public IntegrationEventLogEntry DeserializeJsonContent(Type type) { diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs index 6167d8ae8..cbf363c83 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IIntegrationEventLogService.cs @@ -1,4 +1,5 @@ -using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using System; using System.Collections.Generic; using System.Data.Common; @@ -9,8 +10,8 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Servi { public interface IIntegrationEventLogService { - Task> RetrieveEventLogsPendingToPublishAsync(); - Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction); + Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId); + Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction); Task MarkEventAsPublishedAsync(Guid eventId); Task MarkEventAsInProgressAsync(Guid eventId); Task MarkEventAsFailedAsync(Guid eventId); diff --git a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs index 2712c5e1c..758055e69 100644 --- a/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs +++ b/src/BuildingBlocks/EventBus/IntegrationEventLogEF/Services/IntegrationEventLogService.cs @@ -1,5 +1,6 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus; using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; using Newtonsoft.Json; @@ -34,25 +35,24 @@ namespace Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.Servi .ToList(); } - public async Task> RetrieveEventLogsPendingToPublishAsync() + public async Task> RetrieveEventLogsPendingToPublishAsync(Guid transactionId) { + var tid = transactionId.ToString(); + return await _integrationEventLogContext.IntegrationEventLogs - .Where(e => e.State == EventStateEnum.NotPublished) + .Where(e => e.TransactionId == tid && e.State == EventStateEnum.NotPublished) .OrderBy(o => o.CreationTime) .Select(e => e.DeserializeJsonContent(_eventTypes.Find(t=> t.Name == e.EventTypeShortName))) .ToListAsync(); } - public Task SaveEventAsync(IntegrationEvent @event, DbTransaction transaction) + public Task SaveEventAsync(IntegrationEvent @event, IDbContextTransaction transaction) { - if (transaction == null) - { - throw new ArgumentNullException(nameof(transaction), $"A {typeof(DbTransaction).FullName} is required as a pre-requisite to save the event."); - } + if (transaction == null) throw new ArgumentNullException(nameof(transaction)); - var eventLogEntry = new IntegrationEventLogEntry(@event); + var eventLogEntry = new IntegrationEventLogEntry(@event, transaction.TransactionId); - _integrationEventLogContext.Database.UseTransaction(transaction); + _integrationEventLogContext.Database.UseTransaction(transaction.GetDbTransaction()); _integrationEventLogContext.IntegrationEventLogs.Add(eventLogEntry); return _integrationEventLogContext.SaveChangesAsync(); diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.Designer.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.Designer.cs new file mode 100644 index 000000000..f0d694d07 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.Designer.cs @@ -0,0 +1,50 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + +namespace Catalog.API.Infrastructure.IntegrationEventMigrations +{ + [DbContext(typeof(IntegrationEventLogContext))] + [Migration("20190507184807_AddTransactionId")] + partial class AddTransactionId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd(); + + b.Property("Content") + .IsRequired(); + + b.Property("CreationTime"); + + b.Property("EventTypeName") + .IsRequired(); + + b.Property("State"); + + b.Property("TimesSent"); + + b.Property("TransactionId"); + + b.HasKey("EventId"); + + b.ToTable("IntegrationEventLog"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.cs new file mode 100644 index 000000000..473f26046 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/20190507184807_AddTransactionId.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Catalog.API.Infrastructure.IntegrationEventMigrations +{ + public partial class AddTransactionId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TransactionId", + table: "IntegrationEventLog", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "TransactionId", + table: "IntegrationEventLog"); + } + } +} diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs new file mode 100644 index 000000000..3841e3a20 --- /dev/null +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs @@ -0,0 +1,18 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + +namespace Catalog.API.Infrastructure.IntegrationEventMigrations +{ + public class IntegrationEventLogContextDesignTimeFactory : IDesignTimeDbContextFactory + { + public IntegrationEventLogContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseSqlServer(".", options => options.MigrationsAssembly(GetType().Assembly.GetName().Name)); + + return new IntegrationEventLogContext(optionsBuilder.Options); + } + } +} \ No newline at end of file diff --git a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs index ab2414bb5..672690c14 100644 --- a/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs +++ b/src/Services/Catalog/Catalog.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs @@ -1,8 +1,9 @@ -using System; +// +using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; namespace Catalog.API.Migrations @@ -12,8 +13,10 @@ namespace Catalog.API.Migrations { protected override void BuildModel(ModelBuilder modelBuilder) { +#pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "1.1.1") + .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b => @@ -33,10 +36,13 @@ namespace Catalog.API.Migrations b.Property("TimesSent"); + b.Property("TransactionId"); + b.HasKey("EventId"); b.ToTable("IntegrationEventLog"); }); +#pragma warning restore 612, 618 } } } diff --git a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs index 3b9476b9f..bb3a23d40 100644 --- a/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs +++ b/src/Services/Catalog/Catalog.API/IntegrationEvents/CatalogIntegrationEventService.cs @@ -62,7 +62,7 @@ namespace Catalog.API.IntegrationEvents { // Achieving atomicity between original catalog database operation and the IntegrationEventLog thanks to a local transaction await _catalogContext.SaveChangesAsync(); - await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction.GetDbTransaction()); + await _eventLogService.SaveEventAsync(evt, _catalogContext.Database.CurrentTransaction); }); } } diff --git a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs index d9d3e0b0a..be32daeee 100644 --- a/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs +++ b/src/Services/Ordering/Ordering.API/Application/Behaviors/TransactionBehaviour.cs @@ -42,6 +42,8 @@ namespace Ordering.API.Application.Behaviors await strategy.ExecuteAsync(async () => { + Guid transactionId; + using (var transaction = await _dbContext.BeginTransactionAsync()) using (LogContext.PushProperty("TransactionContext", transaction.TransactionId)) { @@ -52,9 +54,11 @@ namespace Ordering.API.Application.Behaviors _logger.LogInformation("----- Commit transaction {TransactionId} for {CommandName}", transaction.TransactionId, typeName); await _dbContext.CommitTransactionAsync(transaction); + + transactionId = transaction.TransactionId; } - await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync(); + await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync(transactionId); }); return response; diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs index 05e8f0e4f..ad661e3c0 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/IOrderingIntegrationEventService.cs @@ -1,11 +1,12 @@ using Microsoft.eShopOnContainers.BuildingBlocks.EventBus.Events; +using System; using System.Threading.Tasks; namespace Ordering.API.Application.IntegrationEvents { public interface IOrderingIntegrationEventService { - Task PublishEventsThroughEventBusAsync(); + Task PublishEventsThroughEventBusAsync(Guid transactionId); Task AddAndSaveEventAsync(IntegrationEvent evt); } } diff --git a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs index c6360d194..cb7ce5513 100644 --- a/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs +++ b/src/Services/Ordering/Ordering.API/Application/IntegrationEvents/OrderingIntegrationEventService.cs @@ -39,9 +39,9 @@ namespace Ordering.API.Application.IntegrationEvents _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - public async Task PublishEventsThroughEventBusAsync() + public async Task PublishEventsThroughEventBusAsync(Guid transactionId) { - var pendingLogEvents = await _eventLogService.RetrieveEventLogsPendingToPublishAsync(); + var pendingLogEvents = await _eventLogService.RetrieveEventLogsPendingToPublishAsync(transactionId); foreach (var logEvt in pendingLogEvents) { @@ -66,7 +66,7 @@ namespace Ordering.API.Application.IntegrationEvents { _logger.LogInformation("----- Enqueuing integration event {IntegrationEventId} to repository ({@IntegrationEvent})", evt.Id, evt); - await _eventLogService.SaveEventAsync(evt, _orderingContext.GetCurrentTransaction.GetDbTransaction()); + await _eventLogService.SaveEventAsync(evt, _orderingContext.GetCurrentTransaction()); } } } diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.Designer.cs b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.Designer.cs new file mode 100644 index 000000000..b12f0cd15 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.Designer.cs @@ -0,0 +1,50 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + +namespace Ordering.API.Infrastructure.IntegrationEventMigrations +{ + [DbContext(typeof(IntegrationEventLogContext))] + [Migration("20190507185219_AddTransactionId")] + partial class AddTransactionId + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b => + { + b.Property("EventId") + .ValueGeneratedOnAdd(); + + b.Property("Content") + .IsRequired(); + + b.Property("CreationTime"); + + b.Property("EventTypeName") + .IsRequired(); + + b.Property("State"); + + b.Property("TimesSent"); + + b.Property("TransactionId"); + + b.HasKey("EventId"); + + b.ToTable("IntegrationEventLog"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.cs b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.cs new file mode 100644 index 000000000..8ab3699b3 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/20190507185219_AddTransactionId.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Ordering.API.Infrastructure.IntegrationEventMigrations +{ + public partial class AddTransactionId : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "TransactionId", + table: "IntegrationEventLog", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "TransactionId", + table: "IntegrationEventLog"); + } + } +} diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs new file mode 100644 index 000000000..3841e3a20 --- /dev/null +++ b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextDesignTimeFactory.cs @@ -0,0 +1,18 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; + +namespace Catalog.API.Infrastructure.IntegrationEventMigrations +{ + public class IntegrationEventLogContextDesignTimeFactory : IDesignTimeDbContextFactory + { + public IntegrationEventLogContext CreateDbContext(string[] args) + { + var optionsBuilder = new DbContextOptionsBuilder(); + + optionsBuilder.UseSqlServer(".", options => options.MigrationsAssembly(GetType().Assembly.GetName().Name)); + + return new IntegrationEventLogContext(optionsBuilder.Options); + } + } +} \ No newline at end of file diff --git a/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs index 29bd24729..bd3b4edbe 100644 --- a/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs +++ b/src/Services/Ordering/Ordering.API/Infrastructure/IntegrationEventMigrations/IntegrationEventLogContextModelSnapshot.cs @@ -1,8 +1,9 @@ -using System; +// +using System; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF; namespace Ordering.API.Infrastructure.IntegrationEventMigrations @@ -12,8 +13,10 @@ namespace Ordering.API.Infrastructure.IntegrationEventMigrations { protected override void BuildModel(ModelBuilder modelBuilder) { +#pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "1.1.1") + .HasAnnotation("ProductVersion", "2.2.3-servicing-35854") + .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); modelBuilder.Entity("Microsoft.eShopOnContainers.BuildingBlocks.IntegrationEventLogEF.IntegrationEventLogEntry", b => @@ -33,10 +36,13 @@ namespace Ordering.API.Infrastructure.IntegrationEventMigrations b.Property("TimesSent"); + b.Property("TransactionId"); + b.HasKey("EventId"); b.ToTable("IntegrationEventLog"); }); +#pragma warning restore 612, 618 } } } diff --git a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs index 18e72fe29..0b36310ea 100644 --- a/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs +++ b/src/Services/Ordering/Ordering.Infrastructure/OrderingContext.cs @@ -29,7 +29,7 @@ namespace Microsoft.eShopOnContainers.Services.Ordering.Infrastructure private OrderingContext(DbContextOptions options) : base(options) { } - public IDbContextTransaction GetCurrentTransaction => _currentTransaction; + public IDbContextTransaction GetCurrentTransaction() => _currentTransaction; public bool HasActiveTransaction => _currentTransaction != null; diff --git a/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs b/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs index b26d64d40..bbd4b14de 100644 --- a/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs +++ b/src/Services/Payment/Payment.API/IntegrationEvents/EventHandling/OrderStatusChangedToStockConfirmedIntegrationEventHandler.cs @@ -23,6 +23,8 @@ _eventBus = eventBus; _settings = settings.Value; _logger = logger ?? throw new System.ArgumentNullException(nameof(logger)); + + _logger.LogTrace("PaymentSettings: {@PaymentSettings}", _settings); } public async Task Handle(OrderStatusChangedToStockConfirmedIntegrationEvent @event)