diff --git a/application/shared-kernel/ApplicationCore/ApplicationCoreConfiguration.cs b/application/shared-kernel/ApplicationCore/ApplicationCoreConfiguration.cs index 4e3f58da0..fab590a2d 100644 --- a/application/shared-kernel/ApplicationCore/ApplicationCoreConfiguration.cs +++ b/application/shared-kernel/ApplicationCore/ApplicationCoreConfiguration.cs @@ -20,7 +20,7 @@ Assembly applicationAssembly services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnitOfWorkPipelineBehavior<,>)); // Post services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PublishDomainEventsPipelineBehavior<,>)); // Post services.AddScoped(); - services.AddScoped(); + services.AddScoped(); services.AddMediatR(configuration => configuration.RegisterServicesFromAssemblies(applicationAssembly)); services.AddNonGenericValidators(applicationAssembly); diff --git a/application/shared-kernel/ApplicationCore/Behaviors/ConcurrentCommandCounter.cs b/application/shared-kernel/ApplicationCore/Behaviors/ConcurrentCommandCounter.cs new file mode 100644 index 000000000..a2a8c52ed --- /dev/null +++ b/application/shared-kernel/ApplicationCore/Behaviors/ConcurrentCommandCounter.cs @@ -0,0 +1,29 @@ +namespace PlatformPlatform.SharedKernel.ApplicationCore.Behaviors; + +/// +/// The ConcurrentCommandCounter class is a concurrent counter used to count the number of concurrent commands that +/// are being handled. It is used by only commit changes to the database when all commands have been handled. +/// This is to ensure that all changes to all aggregates and entities are committed to the database only after all +/// command and domain events are successfully handled. +/// Additionally, this also ensures that Telemetry is only sent to Application Insights after all commands and +/// domain events are successfully handled. +/// +public sealed class ConcurrentCommandCounter +{ + private int _concurrentCount; + + public void Increment() + { + Interlocked.Increment(ref _concurrentCount); + } + + public void Decrement() + { + Interlocked.Decrement(ref _concurrentCount); + } + + public bool IsZero() + { + return _concurrentCount == 0; + } +} \ No newline at end of file diff --git a/application/shared-kernel/ApplicationCore/Behaviors/PublishTelemetryEventsPipelineBehavior.cs b/application/shared-kernel/ApplicationCore/Behaviors/PublishTelemetryEventsPipelineBehavior.cs index 53dd3c2c1..7fef1ce76 100644 --- a/application/shared-kernel/ApplicationCore/Behaviors/PublishTelemetryEventsPipelineBehavior.cs +++ b/application/shared-kernel/ApplicationCore/Behaviors/PublishTelemetryEventsPipelineBehavior.cs @@ -6,7 +6,8 @@ namespace PlatformPlatform.SharedKernel.ApplicationCore.Behaviors; public sealed class PublishTelemetryEventsPipelineBehavior( ITelemetryEventsCollector telemetryEventsCollector, - TelemetryClient telemetryClient + TelemetryClient telemetryClient, + ConcurrentCommandCounter concurrentCommandCounter ) : IPipelineBehavior where TRequest : ICommand where TResponse : ResultBase { public async Task Handle( @@ -17,10 +18,13 @@ CancellationToken cancellationToken { var result = await next(); - while (telemetryEventsCollector.HasEvents) + if (concurrentCommandCounter.IsZero()) { - var telemetryEvent = telemetryEventsCollector.Dequeue(); - telemetryClient.TrackEvent(telemetryEvent.Name, telemetryEvent.Properties); + while (telemetryEventsCollector.HasEvents) + { + var telemetryEvent = telemetryEventsCollector.Dequeue(); + telemetryClient.TrackEvent(telemetryEvent.Name, telemetryEvent.Properties); + } } return result; diff --git a/application/shared-kernel/ApplicationCore/Behaviors/UnitOfWorkPipelineBehavior.cs b/application/shared-kernel/ApplicationCore/Behaviors/UnitOfWorkPipelineBehavior.cs index 9a0cd9519..5ea26d99c 100644 --- a/application/shared-kernel/ApplicationCore/Behaviors/UnitOfWorkPipelineBehavior.cs +++ b/application/shared-kernel/ApplicationCore/Behaviors/UnitOfWorkPipelineBehavior.cs @@ -12,7 +12,7 @@ namespace PlatformPlatform.SharedKernel.ApplicationCore.Behaviors; /// public sealed class UnitOfWorkPipelineBehavior( IUnitOfWork unitOfWork, - UnitOfWorkPipelineBehaviorConcurrentCounter unitOfWorkPipelineBehaviorConcurrentCounter + ConcurrentCommandCounter concurrentCommandCounter ) : IPipelineBehavior where TRequest : ICommand where TResponse : ResultBase { public async Task Handle( @@ -21,13 +21,13 @@ public async Task Handle( CancellationToken cancellationToken ) { - unitOfWorkPipelineBehaviorConcurrentCounter.Increment(); + concurrentCommandCounter.Increment(); var response = await next(); if (response is ResultBase { IsSuccess: true }) { - unitOfWorkPipelineBehaviorConcurrentCounter.Decrement(); - if (unitOfWorkPipelineBehaviorConcurrentCounter.IsZero()) + concurrentCommandCounter.Decrement(); + if (concurrentCommandCounter.IsZero()) { await unitOfWork.CommitAsync(cancellationToken); } diff --git a/application/shared-kernel/ApplicationCore/Behaviors/UnitOfWorkPipelineBehaviorConcurrentCounter.cs b/application/shared-kernel/ApplicationCore/Behaviors/UnitOfWorkPipelineBehaviorConcurrentCounter.cs deleted file mode 100644 index 9bca99401..000000000 --- a/application/shared-kernel/ApplicationCore/Behaviors/UnitOfWorkPipelineBehaviorConcurrentCounter.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace PlatformPlatform.SharedKernel.ApplicationCore.Behaviors; - -/// -/// The UnitOfWorkPipelineBehaviorConcurrentCounter class is a concurrent counter used to count the number of -/// concurrent commands that are being handled by the UnitOfWorkPipelineBehavior. It is used by only commit changes -/// to the database when all commands have been handled. This is to ensure that all changes to all aggregates and -/// entities are committed to the database only after all command and domain events are successfully handled. -/// -public sealed class UnitOfWorkPipelineBehaviorConcurrentCounter -{ - private int _concurrentCount; - - public void Increment() - { - Interlocked.Increment(ref _concurrentCount); - } - - public void Decrement() - { - Interlocked.Decrement(ref _concurrentCount); - } - - public bool IsZero() - { - return _concurrentCount == 0; - } -} \ No newline at end of file diff --git a/application/shared-kernel/Tests/ApplicationCore/Behaviors/UnitOfWorkPipelineBehaviorTests.cs b/application/shared-kernel/Tests/ApplicationCore/Behaviors/UnitOfWorkPipelineBehaviorTests.cs index d8937f417..88f6330ea 100644 --- a/application/shared-kernel/Tests/ApplicationCore/Behaviors/UnitOfWorkPipelineBehaviorTests.cs +++ b/application/shared-kernel/Tests/ApplicationCore/Behaviors/UnitOfWorkPipelineBehaviorTests.cs @@ -20,7 +20,7 @@ public UnitOfWorkPipelineBehaviorTests() services.AddSingleton(_unitOfWork); _behavior = new UnitOfWorkPipelineBehavior>( _unitOfWork, - new UnitOfWorkPipelineBehaviorConcurrentCounter() + new ConcurrentCommandCounter() ); }