From fc1872c5e714ac98826aca71390ad2a5e172bab5 Mon Sep 17 00:00:00 2001 From: Magnus Sandgren <5285192+MagnusSandgren@users.noreply.github.com> Date: Mon, 14 Oct 2024 15:46:19 +0200 Subject: [PATCH] Rename --- .../InfrastructureExtensions.cs | 2 +- .../IIdempotentNotificationContext.cs | 40 ----------------- ...n.cs => INotificationProcessingContext.cs} | 6 +-- .../INotificationProcessingContextFactory.cs | 43 +++++++++++++++++++ .../IdempotentNotificationHandler.cs | 8 ++-- .../Consumers/DomainEventConsumer.cs | 12 +++--- 6 files changed, 57 insertions(+), 54 deletions(-) delete mode 100644 src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IIdempotentNotificationContext.cs rename src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/{IIdempotentNotificationTransaction.cs => INotificationProcessingContext.cs} (92%) create mode 100644 src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/INotificationProcessingContextFactory.cs diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs index 50ed28259..df9a3350b 100644 --- a/src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs @@ -87,7 +87,7 @@ internal static void AddInfrastructure_Internal(InfrastructureBuilderContext bui .AddTransient() // Singleton - .AddSingleton() + .AddSingleton() // HttpClient .AddHttpClients(configuration.GetSection(InfrastructureSettings.ConfigurationSectionName)) diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IIdempotentNotificationContext.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IIdempotentNotificationContext.cs deleted file mode 100644 index 7126e4bdc..000000000 --- a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IIdempotentNotificationContext.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Collections.Concurrent; -using Digdir.Domain.Dialogporten.Domain.Common.EventPublisher; -using Microsoft.Extensions.DependencyInjection; - -namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence.IdempotentNotifications; - -public interface IIdempotentNotificationContext -{ - Task BeginTransaction(IDomainEvent domainEvent, bool isFirstAttempt = false, CancellationToken cancellationToken = default); - IIdempotentNotificationTransaction GetExistingTransaction(Guid eventId); -} - -internal sealed class IdempotentNotificationContext : IIdempotentNotificationContext -{ - private readonly ConcurrentDictionary _transactionsByEventId = new(); - private readonly IServiceScopeFactory _serviceScopeFactory; - - public IdempotentNotificationContext(IServiceScopeFactory serviceScopeFactory) - { - _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory)); - } - - public async Task BeginTransaction(IDomainEvent domainEvent, bool isFirstAttempt = false, CancellationToken cancellationToken = default) - { - var transaction = _transactionsByEventId.GetOrAdd( - key: domainEvent.EventId, - valueFactory: eventId => new(_serviceScopeFactory, eventId, onDispose: RemoveTransaction)); - await transaction.Initialize(isFirstAttempt, cancellationToken); - return transaction; - } - - public IIdempotentNotificationTransaction GetExistingTransaction(Guid eventId) - { - return _transactionsByEventId.TryGetValue(eventId, out var transaction) - ? transaction - : throw new InvalidOperationException("Transaction not found."); - } - - private void RemoveTransaction(Guid eventId) => _transactionsByEventId.TryRemove(eventId, out _); -} diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IIdempotentNotificationTransaction.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/INotificationProcessingContext.cs similarity index 92% rename from src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IIdempotentNotificationTransaction.cs rename to src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/INotificationProcessingContext.cs index 85792e14f..afaf40b41 100644 --- a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IIdempotentNotificationTransaction.cs +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/INotificationProcessingContext.cs @@ -4,7 +4,7 @@ namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence.IdempotentNotifications; -public interface IIdempotentNotificationTransaction : IAsyncDisposable +public interface INotificationProcessingContext : IAsyncDisposable { Task Ack(CancellationToken cancellationToken = default); Task Nack(CancellationToken cancellationToken = default); @@ -12,7 +12,7 @@ public interface IIdempotentNotificationTransaction : IAsyncDisposable Task HandlerIsAcked(string handlerName, CancellationToken cancellationToken = default); } -internal sealed class IdempotentNotificationTransaction : IIdempotentNotificationTransaction +internal sealed class NotificationProcessingContext : INotificationProcessingContext { private readonly SemaphoreSlim _initializeLock = new(1, 1); private readonly IServiceScopeFactory _serviceScopeFactory; @@ -23,7 +23,7 @@ internal sealed class IdempotentNotificationTransaction : IIdempotentNotificatio private IServiceScope? _serviceScope; private bool _acknowledged; - public IdempotentNotificationTransaction(IServiceScopeFactory serviceScopeFactory, Guid eventId, Action onDispose) + public NotificationProcessingContext(IServiceScopeFactory serviceScopeFactory, Guid eventId, Action onDispose) { _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory)); _onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose)); diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/INotificationProcessingContextFactory.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/INotificationProcessingContextFactory.cs new file mode 100644 index 000000000..0c1d81817 --- /dev/null +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/INotificationProcessingContextFactory.cs @@ -0,0 +1,43 @@ +using System.Collections.Concurrent; +using Digdir.Domain.Dialogporten.Domain.Common.EventPublisher; +using Microsoft.Extensions.DependencyInjection; + +namespace Digdir.Domain.Dialogporten.Infrastructure.Persistence.IdempotentNotifications; + +public interface INotificationProcessingContextFactory +{ + Task CreateContext(IDomainEvent domainEvent, bool isFirstAttempt = false, CancellationToken cancellationToken = default); + INotificationProcessingContext GetExistingContext(Guid eventId); +} + +internal sealed class NotificationProcessingContextFactory : INotificationProcessingContextFactory +{ + private readonly ConcurrentDictionary _contextByEventId = new(); + private readonly IServiceScopeFactory _serviceScopeFactory; + + public NotificationProcessingContextFactory(IServiceScopeFactory serviceScopeFactory) + { + _serviceScopeFactory = serviceScopeFactory ?? throw new ArgumentNullException(nameof(serviceScopeFactory)); + } + + public async Task CreateContext( + IDomainEvent domainEvent, + bool isFirstAttempt = false, + CancellationToken cancellationToken = default) + { + var transaction = _contextByEventId.GetOrAdd( + key: domainEvent.EventId, + valueFactory: eventId => new(_serviceScopeFactory, eventId, onDispose: RemoveTransaction)); + await transaction.Initialize(isFirstAttempt, cancellationToken); + return transaction; + } + + public INotificationProcessingContext GetExistingContext(Guid eventId) + { + return _contextByEventId.TryGetValue(eventId, out var transaction) + ? transaction + : throw new InvalidOperationException("Notification context not found."); + } + + private void RemoveTransaction(Guid eventId) => _contextByEventId.TryRemove(eventId, out _); +} diff --git a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IdempotentNotificationHandler.cs b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IdempotentNotificationHandler.cs index e6a1ff45b..85d6519bf 100644 --- a/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IdempotentNotificationHandler.cs +++ b/src/Digdir.Domain.Dialogporten.Infrastructure/Persistence/IdempotentNotifications/IdempotentNotificationHandler.cs @@ -13,18 +13,18 @@ internal sealed class IdempotentNotificationHandler : where TNotification : IDomainEvent { private readonly INotificationHandler _decorated; - private readonly IIdempotentNotificationContext _context; + private readonly INotificationProcessingContextFactory _processingContextFactory; - public IdempotentNotificationHandler(INotificationHandler decorated, IIdempotentNotificationContext context) + public IdempotentNotificationHandler(INotificationHandler decorated, INotificationProcessingContextFactory processingContextFactory) { _decorated = decorated ?? throw new ArgumentNullException(nameof(decorated)); - _context = context ?? throw new ArgumentNullException(nameof(context)); + _processingContextFactory = processingContextFactory ?? throw new ArgumentNullException(nameof(processingContextFactory)); } public async Task Handle(TNotification notification, CancellationToken cancellationToken) { var handlerName = _decorated.GetType().FullName!; - var transaction = _context.GetExistingTransaction(notification.EventId); + var transaction = _processingContextFactory.GetExistingContext(notification.EventId); if (await transaction.HandlerIsAcked(handlerName, cancellationToken)) { // I've handled this event before, so I'm not going to do it again. diff --git a/src/Digdir.Domain.Dialogporten.Service/Consumers/DomainEventConsumer.cs b/src/Digdir.Domain.Dialogporten.Service/Consumers/DomainEventConsumer.cs index 4529cdcbc..b93f4c137 100644 --- a/src/Digdir.Domain.Dialogporten.Service/Consumers/DomainEventConsumer.cs +++ b/src/Digdir.Domain.Dialogporten.Service/Consumers/DomainEventConsumer.cs @@ -9,21 +9,21 @@ public sealed class DomainEventConsumer : IConsumer where T : class, IDomainEvent { private readonly IPublisher _publisher; - private readonly IIdempotentNotificationContext _notificationContext; + private readonly INotificationProcessingContextFactory _notificationProcessingContextFactory; - public DomainEventConsumer(IPublisher publisher, IIdempotentNotificationContext notificationContext) + public DomainEventConsumer(IPublisher publisher, INotificationProcessingContextFactory notificationProcessingContextFactory) { _publisher = publisher ?? throw new ArgumentNullException(nameof(publisher)); - _notificationContext = notificationContext ?? throw new ArgumentNullException(nameof(notificationContext)); + _notificationProcessingContextFactory = notificationProcessingContextFactory ?? throw new ArgumentNullException(nameof(notificationProcessingContextFactory)); } public async Task Consume(ConsumeContext context) { var isFirstAttempt = IsFirstAttempt(context); - await using var transaction = await _notificationContext - .BeginTransaction(context.Message, isFirstAttempt, context.CancellationToken); + await using var notificationContext = await _notificationProcessingContextFactory + .CreateContext(context.Message, isFirstAttempt, context.CancellationToken); await _publisher.Publish(context.Message, context.CancellationToken); - await transaction.Ack(context.CancellationToken); + await notificationContext.Ack(context.CancellationToken); } private static bool IsFirstAttempt(ConsumeContext context)