From 01d13dbbf20dcc630b6bac6c402370c607ed61be18d6d1fac0d322cf1ac86f64 Mon Sep 17 00:00:00 2001 From: Navid Filsaraee Date: Tue, 22 Sep 2026 16:26:16 +0330 Subject: [PATCH] feat: update settlement workflow --- application/settlement/worker.go | 9 ++++++++- domain/ledger/settlement.go | 5 +++++ infrastructure/kuknos/submitter.go | 3 +++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/application/settlement/worker.go b/application/settlement/worker.go index 1a6c50d..52f914b 100644 --- a/application/settlement/worker.go +++ b/application/settlement/worker.go @@ -2,6 +2,7 @@ package settlement import ( "context" + "errors" "fmt" "time" @@ -41,7 +42,13 @@ func (w Worker) RunOnce(ctx context.Context, limit int) error { record.Attempts++ hash, submitErr := w.Submitter.Submit(ctx, record) if submitErr != nil { - record = record.Retry(now, w.MaxAttempts, submitErr) + var permanent ledger.PermanentSubmissionError + if errors.As(submitErr, &permanent) { + record.Status = ledger.SettlementManualReview + record.LastError = submitErr.Error() + } else { + record = record.Retry(now, w.MaxAttempts, submitErr) + } } else { // Horizon returns success only after the transaction is accepted into // a ledger, so a successful response is already confirmation. diff --git a/domain/ledger/settlement.go b/domain/ledger/settlement.go index 0b9b586..5dec533 100644 --- a/domain/ledger/settlement.go +++ b/domain/ledger/settlement.go @@ -5,6 +5,11 @@ import ( "time" ) +type PermanentSubmissionError struct{ Err error } + +func (e PermanentSubmissionError) Error() string { return e.Err.Error() } +func (e PermanentSubmissionError) Unwrap() error { return e.Err } + type SettlementStatus string const ( diff --git a/infrastructure/kuknos/submitter.go b/infrastructure/kuknos/submitter.go index 167769b..6bbeae1 100644 --- a/infrastructure/kuknos/submitter.go +++ b/infrastructure/kuknos/submitter.go @@ -119,6 +119,9 @@ func (s Submitter) Submit(ctx context.Context, record ledger.Settlement) (string err := fmt.Errorf("kuknos rejected transaction: status=%d code=%s", resp.StatusCode, response.Extras.ResultCodes.Transaction) span.SetStatus(codes.Error, err.Error()) span.RecordError(err) + if response.Extras.ResultCodes.Transaction == "tx_bad_seq" { + return "", ledger.PermanentSubmissionError{Err: err} + } return "", err } return response.Hash, nil