using Infrastructure; using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using QRCodeService.Extensions; using Serilog.Context; using System; using System.Threading; using System.Threading.Tasks; namespace QRCodeService.Application.Behaviors { public class TransactionBehaviour : IPipelineBehavior { private readonly ILogger> _logger; private readonly AppDbContext _dbContext; //private readonly IOrderingIntegrationEventService _orderingIntegrationEventService; public TransactionBehaviour(AppDbContext dbContext, //IOrderingIntegrationEventService orderingIntegrationEventService, ILogger> logger) { _dbContext = dbContext ?? throw new ArgumentException(nameof(AppDbContext)); //_orderingIntegrationEventService = orderingIntegrationEventService ?? throw new ArgumentException(nameof(orderingIntegrationEventService)); _logger = logger ?? throw new ArgumentException(nameof(ILogger)); } public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) { var response = default(TResponse); var typeName = request.GetGenericTypeName(); try { if (_dbContext.HasActiveTransaction) { return await next(); } var strategy = _dbContext.Database.CreateExecutionStrategy(); await strategy.ExecuteAsync(async () => { Guid transactionId; using (var transaction = await _dbContext.BeginTransactionAsync()) using (LogContext.PushProperty("TransactionContext", transaction.TransactionId)) { _logger.LogInformation("----- Begin transaction {TransactionId} for {CommandName} ({@Command})", transaction.TransactionId, typeName, request); response = await next(); _logger.LogInformation("----- Commit transaction {TransactionId} for {CommandName}", transaction.TransactionId, typeName); await _dbContext.CommitTransactionAsync(transaction); transactionId = transaction.TransactionId; } //await _orderingIntegrationEventService.PublishEventsThroughEventBusAsync(transactionId); }); return response; } catch (Exception ex) { _logger.LogError(ex, "ERROR Handling transaction for {CommandName} ({@Command})", typeName, request); throw; } } } }