From 80f421a0826ed8aec1ba3e61dac95ac9040b15b3 Mon Sep 17 00:00:00 2001 From: Nikoo Asadnejad Date: Thu, 7 Nov 2024 14:31:10 +0330 Subject: [PATCH] feat: add outboxMessage interceptor --- .../OutBoxMessage/Entities/OutBoxMessage.cs | 2 +- .../AddOutboxMessageInterceptor.cs | 67 +++++++++++++++++++ .../PublishDomainEventsInterceptor.cs | 1 - .../OutBoxMessageConfiguration.cs | 2 + .../Ioc/GenericRepositoryConfigurator.cs | 1 + 5 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 GenericRepository/Infrastructure/EfInterceptors/AddOutboxMessageInterceptor.cs diff --git a/GenericRepository/Domain/OutBoxMessage/Entities/OutBoxMessage.cs b/GenericRepository/Domain/OutBoxMessage/Entities/OutBoxMessage.cs index a95c9ba..cacf4a2 100644 --- a/GenericRepository/Domain/OutBoxMessage/Entities/OutBoxMessage.cs +++ b/GenericRepository/Domain/OutBoxMessage/Entities/OutBoxMessage.cs @@ -15,7 +15,7 @@ private OutBoxMessage(string type, string content, EventType = new OutBoxMessageEventType(eventType); } - public OutBoxMessage CreateByDomainEvent(IDomainEvent domainEvent) + public static OutBoxMessage CreateByDomainEvent(IDomainEvent domainEvent) { return new OutBoxMessage(domainEvent.GetType().Name, JsonSerializer.Serialize(domainEvent)); } diff --git a/GenericRepository/Infrastructure/EfInterceptors/AddOutboxMessageInterceptor.cs b/GenericRepository/Infrastructure/EfInterceptors/AddOutboxMessageInterceptor.cs new file mode 100644 index 0000000..1afb6cc --- /dev/null +++ b/GenericRepository/Infrastructure/EfInterceptors/AddOutboxMessageInterceptor.cs @@ -0,0 +1,67 @@ +using GenericRepository.Application.Interfaces.UnitOfWork; +using GenericRepository.Domain; +using GenericRepository.Domain.Entities; +using GenericRepository.Infrastructure.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; + +namespace GenericRepository.Infrastructure.EfInterceptors; + +public sealed class AddOutboxMessageInterceptor(IUnitOfWork unitOfWork) : SaveChangesInterceptor +{ + public override InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result) + { + var context = eventData.Context; + if (context != null) + { + BeforeSave(context); + } + + return base.SavingChanges(eventData, result); + } + + public override ValueTask> SavingChangesAsync( + DbContextEventData eventData, + InterceptionResult result, + CancellationToken cancellationToken = default) + { + var context = eventData.Context; + + if (context != null) + { + BeforeSave(context); + } + + return base.SavingChangesAsync(eventData, result, cancellationToken); + } + + private void BeforeSave(DbContext context) + { + var domainEvents = GetDomainEvents(context); + + foreach (IDomainEvent domainEvent in domainEvents) + { + var outboxMessage = OutBoxMessage.CreateByDomainEvent(domainEvent); + unitOfWork.OutboxMessages.Add(outboxMessage); + } + + unitOfWork.Save(); + } + private static List GetDomainEvents(DbContext context) + { + var domainEvents = context + .ChangeTracker + .Entries() + .Select(entry => entry.Entity) + .Where(e=> e.DomainEvents.Any()) + .SelectMany(entity => + { + IReadOnlyList domainEvents = entity.DomainEvents; + entity.ClearDomainEvents(); + return domainEvents; + }) + .ToList(); + + return domainEvents; + } +} \ No newline at end of file diff --git a/GenericRepository/Infrastructure/EfInterceptors/PublishDomainEventsInterceptor.cs b/GenericRepository/Infrastructure/EfInterceptors/PublishDomainEventsInterceptor.cs index c118519..f9db9ef 100644 --- a/GenericRepository/Infrastructure/EfInterceptors/PublishDomainEventsInterceptor.cs +++ b/GenericRepository/Infrastructure/EfInterceptors/PublishDomainEventsInterceptor.cs @@ -8,7 +8,6 @@ namespace GenericRepository.Infrastructure.EfInterceptors; public sealed class PublishDomainEventsInterceptor : SaveChangesInterceptor { private readonly IPublisher _publisher; - public PublishDomainEventsInterceptor(IPublisher publisher) { _publisher = publisher; diff --git a/GenericRepository/Infrastructure/EntitytypeConfigurations/OutBoxMessageConfiguration.cs b/GenericRepository/Infrastructure/EntitytypeConfigurations/OutBoxMessageConfiguration.cs index 867c519..ce6640b 100644 --- a/GenericRepository/Infrastructure/EntitytypeConfigurations/OutBoxMessageConfiguration.cs +++ b/GenericRepository/Infrastructure/EntitytypeConfigurations/OutBoxMessageConfiguration.cs @@ -33,5 +33,7 @@ public void Configure(EntityTypeBuilder builder) { e.WithOwner(); }); + + builder.Ignore(b => b.IsProcessed); } } \ No newline at end of file diff --git a/GenericRepository/Infrastructure/Ioc/GenericRepositoryConfigurator.cs b/GenericRepository/Infrastructure/Ioc/GenericRepositoryConfigurator.cs index 6ffa3a2..6882639 100644 --- a/GenericRepository/Infrastructure/Ioc/GenericRepositoryConfigurator.cs +++ b/GenericRepository/Infrastructure/Ioc/GenericRepositoryConfigurator.cs @@ -21,6 +21,7 @@ public static void InjectServices(IServiceCollection services) services.AddScoped(); services.AddScoped(); services.AddSingleton(); + services.AddSingleton(); services.AddTransient(typeof(IRepository<>), typeof(Repository<>)); services.AddTransient(typeof(IQueryGenericRepository<>), typeof(QueryGenericRepository<>)); services.Decorate(typeof(IQueryGenericRepository<>), typeof(CacheRepository<>));