using KArtSell.Modules.ModelOperations.ShadowRun.Events; using Microsoft.Extensions.Logging; namespace KArtSell.Host.Consumers; /// /// Creates approval queue entries when shadow run passes all validation gates. /// Idempotent: INSERT ... ON CONFLICT DO NOTHING ensures no duplicates. /// Triggers: Approval workflow notification to model owner/manager. /// public sealed class ApprovalQueueConsumer : IInboxConsumer { private readonly ILogger _logger; public ApprovalQueueConsumer(ILogger logger) { _logger = logger; } public async Task HandleAsync(ShadowRunCompletedEvent message, CancellationToken cancellationToken = default) { try { // Only create approval queue if all gates passed if (!message.AllGatesPassed) { _logger.LogInformation( "Shadow run {RunId} failed gates; skipping approval queue", message.RunId); return; } _logger.LogInformation( "Creating approval queue entry for shadow run {RunId}, model {ModelId}", message.RunId, message.ModelId); // TODO: Implement database insert to approval_queue table // INSERT INTO approval_queue (run_id, model_id, status, requested_at) // VALUES (@runId, @modelId, 'Pending', @now) // ON CONFLICT (run_id) DO NOTHING; -- Idempotent // Simulated: In production, this would call a repository or query service await Task.Delay(10, cancellationToken); // Simulate DB work _logger.LogInformation( "Approval queue entry created for {RunId}", message.RunId); } catch (Exception ex) { _logger.LogError(ex, "Failed to create approval queue entry for {RunId}", message.RunId); throw; // Let Hangfire classify } } }