2026-01-10 11:13:33 +01:00
|
|
|
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<ProcessOutboxCommand>
|
|
|
|
|
{
|
|
|
|
|
public async Task<CommandResponse> Handle(ProcessOutboxCommand command)
|
|
|
|
|
{
|
2026-01-10 20:39:17 +01:00
|
|
|
Console.WriteLine($"ProcessOutboxHandler started");
|
2026-01-10 11:13:33 +01:00
|
|
|
telemetryClient.TrackTrace($"ProcessOutboxHandler started");
|
|
|
|
|
|
|
|
|
|
var messages = await outboxService.GetPendingAsync(command.BatchSize);
|
|
|
|
|
|
2026-01-10 20:39:17 +01:00
|
|
|
Console.WriteLine($"ProcessOutboxHandler found {messages.Count} pending messages");
|
2026-01-10 11:13:33 +01:00
|
|
|
telemetryClient.TrackTrace($"ProcessOutboxHandler found {messages.Count} pending messages");
|
|
|
|
|
|
|
|
|
|
foreach (var message in messages)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2026-01-10 20:39:17 +01:00
|
|
|
Console.WriteLine($"Processing message {message.Id} of type {message.Type}");
|
2026-01-10 11:13:33 +01:00
|
|
|
telemetryClient.TrackTrace($"Processing message {message.Id} of type {message.Type}");
|
|
|
|
|
await ProcessMessageAsync(message);
|
|
|
|
|
await outboxService.MarkAsSentAsync(message.Id);
|
2026-01-10 20:39:17 +01:00
|
|
|
Console.WriteLine($"Message {message.Id} marked as sent");
|
2026-01-10 11:13:33 +01:00
|
|
|
telemetryClient.TrackTrace($"Message {message.Id} marked as sent");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
2026-01-10 20:39:17 +01:00
|
|
|
Console.WriteLine($"Message {message.Id} failed: {ex.Message}");
|
2026-01-10 11:13:33 +01:00
|
|
|
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<VerificationEmailPayload>()
|
|
|
|
|
?? 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}");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|