using Femto.Common.Domain; using Femto.Modules.Blog.Data; using MediatR; using Microsoft.Extensions.Logging; namespace Femto.Modules.Blog.Infrastructure.PipelineBehaviours; internal class SaveChangesPipelineBehaviour( BlogContext context, IPublisher publisher, ILogger> logger ) : IPipelineBehavior where TRequest : notnull { public async Task Handle( TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken ) { var response = await next(cancellationToken); if (context.ChangeTracker.HasChanges()) { await EmitDomainEvents(cancellationToken); logger.LogDebug("saving changes"); await context.SaveChangesAsync(cancellationToken); } return response; } private async Task EmitDomainEvents(CancellationToken cancellationToken) { var domainEvents = context .ChangeTracker.Entries() .SelectMany(e => { var events = e.Entity.DomainEvents; e.Entity.ClearDomainEvents(); return events; }) .ToList(); logger.LogTrace("loaded {Count} domain events", domainEvents.Count); foreach (var domainEvent in domainEvents) { logger.LogTrace( "publishing {Type} domain event {Id}", domainEvent.GetType().Name, domainEvent.EventId ); await publisher.Publish(domainEvent, cancellationToken); } } }