using Kbx.Shared.Integrations.Generated; using Shared.Operations; namespace Kbx.Shared.Integrations; public sealed class KbxIntegrationOperationsProjector(OperationsProjectionWriter operations) { private const string Code = "INTEGRATION_FAILED"; public Task OnPermanentFailureAsync( KbxIntegrationMessage message, KbxIntegrationDefinition definition, KbxIntegrationAttemptResult result, CancellationToken ct) => operations.UpsertAsync(new UpsertWorkItem( TenantId: message.TenantId.ToString(), SourceModule: definition.OwnerModule, SourceType: "Integration", SourceId: message.MessageId.ToString(), ReferenceNo: message.AggregateId, SourceScreenId: null, SourceVersion: message.AggregateVersion, Code: Code, Title: $"{definition.Title} 실패", Detail: result.Detail ?? result.Code, Severity: definition.Criticality == "high" ? "critical" : "warning", OccurredAt: DateTimeOffset.UtcNow, RetryActionKey: definition.Idempotency == "none" ? null : "integration.retry", AllowManualResolution: false, Context: new { message.IntegrationId, message.CorrelationId, result.Code, result.HttpStatus }), ct); public Task OnDeliveredAsync(KbxIntegrationMessage message, KbxIntegrationDefinition definition, CancellationToken ct) => operations.ResolveBySourceAsync( message.TenantId.ToString(), definition.OwnerModule, "Integration", message.MessageId.ToString(), Code, "외부 연계 전달 완료", message.AggregateVersion, ct); }