using Dapper; using Npgsql; namespace Kbx.Shared.Integrations; public sealed class KbxIntegrationAttemptRepository(NpgsqlDataSource dataSource) { public async Task StartAsync(KbxIntegrationMessage message, int attemptNo, CancellationToken ct) { const string sql = """ insert into kbx.integration_attempts(id, tenant_id, integration_id, message_id, aggregate_type, aggregate_id, aggregate_version, attempt_no, state, correlation_id, started_at) values (@Id,@TenantId,@IntegrationId,@MessageId,@AggregateType,@AggregateId,@AggregateVersion,@AttemptNo,'delivering',@CorrelationId,now()) on conflict (tenant_id,integration_id,message_id,attempt_no) do update set correlation_id=excluded.correlation_id returning id; """; await using var connection = await dataSource.OpenConnectionAsync(ct); return await connection.ExecuteScalarAsync(new CommandDefinition(sql, new { Id=Guid.NewGuid(), message.TenantId, message.IntegrationId, message.MessageId, message.AggregateType, message.AggregateId, message.AggregateVersion, AttemptNo=attemptNo, message.CorrelationId }, cancellationToken:ct)); } public async Task CompleteAsync(Guid id, KbxIntegrationAttemptResult result, string state, DateTimeOffset? nextRetryAt, CancellationToken ct) { const string sql = """ update kbx.integration_attempts set state=@State, completed_at=now(), failure_kind=@FailureKind, failure_code=@Code, detail=@Detail, http_status=@HttpStatus, external_reference=@ExternalReference, next_retry_at=@NextRetryAt where id=@Id; """; await using var connection=await dataSource.OpenConnectionAsync(ct); await connection.ExecuteAsync(new CommandDefinition(sql,new { Id=id, State=state, FailureKind=result.FailureKind?.ToString().ToLowerInvariant(), result.Code, result.Detail, result.HttpStatus, result.ExternalReference, NextRetryAt=nextRetryAt },cancellationToken:ct)); } }