using System.Text.Json; using Microsoft.ApplicationInsights; using PlanTempus.Core.CommandQueries; using PlanTempus.Core.Email; using PlanTempus.Core.Outbox; namespace PlanTempus.Components.Outbox; public class ProcessOutboxHandler( IOutboxService outboxService, IEmailService emailService, TelemetryClient telemetryClient) : ICommandHandler { public async Task Handle(ProcessOutboxCommand command) { telemetryClient.TrackTrace($"ProcessOutboxHandler started"); var messages = await outboxService.GetPendingAsync(command.BatchSize); telemetryClient.TrackTrace($"ProcessOutboxHandler found {messages.Count} pending messages"); foreach (var message in messages) { try { telemetryClient.TrackTrace($"Processing message {message.Id} of type {message.Type}"); await ProcessMessageAsync(message); await outboxService.MarkAsSentAsync(message.Id); telemetryClient.TrackTrace($"Message {message.Id} marked as sent"); } catch (Exception ex) { telemetryClient.TrackTrace($"Message {message.Id} failed: {ex.Message}"); await outboxService.MarkAsFailedAsync(message.Id, ex.Message); } } return new CommandResponse(command.CorrelationId, nameof(ProcessOutboxCommand), command.TransactionId); } private async Task ProcessMessageAsync(OutboxMessage message) { switch (message.Type) { case OutboxMessageTypes.VerificationEmail: await ProcessVerificationEmailAsync(message); break; default: throw new InvalidOperationException($"Unknown outbox message type: {message.Type}"); } } private async Task ProcessVerificationEmailAsync(OutboxMessage message) { var payload = ((JsonElement)message.Payload).Deserialize() ?? throw new InvalidOperationException("Invalid verification email payload"); var verifyUrl = $"https://plantempus.dk/confirm-email?token={payload.Token}"; var result = await emailService.SendVerificationEmailAsync( payload.Email, payload.UserName, verifyUrl); if (!result.Success) { throw new InvalidOperationException($"Failed to send email: {result.ErrorMessage}"); } } }