multi: implement Fail method for sql backend
This commit is contained in:
4 files changed
+83
No files matched your search
@@ -77,6 +77,8 @@ type SQLQueries interface {
|
|||||||
|
|
||||||
SettleAttempt(ctx context.Context, arg sqlc.SettleAttemptParams) error
|
SettleAttempt(ctx context.Context, arg sqlc.SettleAttemptParams) error
|
||||||
|
|
||||||
|
FailPayment(ctx context.Context, arg sqlc.FailPaymentParams) (sql.Result, error)
|
||||||
|
|
||||||
DeletePayment(ctx context.Context, paymentID int64) error
|
DeletePayment(ctx context.Context, paymentID int64) error
|
||||||
|
|
||||||
// DeleteFailedAttempts removes all failed HTLCs from the db for a
|
// DeleteFailedAttempts removes all failed HTLCs from the db for a
|
||||||
@@ -1360,3 +1362,67 @@ func (s *SQLStore) SettleAttempt(paymentHash lntypes.Hash,
|
|||||||
|
|
||||||
return mpPayment, nil
|
return mpPayment, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fail records the ultimate reason why a payment failed. This method stores
|
||||||
|
// the failure reason for record keeping but does not enforce that all HTLC
|
||||||
|
// attempts are resolved - HTLCs may still be in flight when this is called.
|
||||||
|
//
|
||||||
|
// The payment's actual status transition to StatusFailed is determined by the
|
||||||
|
// payment state calculation, which considers both the recorded failure reason
|
||||||
|
// and the current state of all HTLC attempts. The status will transition to
|
||||||
|
// StatusFailed once all HTLCs are resolved and/or a failure reason is recorded.
|
||||||
|
//
|
||||||
|
// NOTE: According to the interface contract, this should only be called when
|
||||||
|
// all active attempts are already failed. However, the implementation allows
|
||||||
|
// concurrent calls and does not validate this precondition, enabling the last
|
||||||
|
// failing attempt to record the failure reason without synchronization.
|
||||||
|
//
|
||||||
|
// This method is part of the PaymentControl interface, which is embedded in
|
||||||
|
// the PaymentWriter interface and ultimately the DB interface. It represents
|
||||||
|
// step 4 in the payment lifecycle control flow.
|
||||||
|
func (s *SQLStore) Fail(paymentHash lntypes.Hash,
|
||||||
|
reason FailureReason) (*MPPayment, error) {
|
||||||
|
|
||||||
|
ctx := context.TODO()
|
||||||
|
|
||||||
|
var mpPayment *MPPayment
|
||||||
|
|
||||||
|
err := s.db.ExecTx(ctx, sqldb.WriteTxOpt(), func(db SQLQueries) error {
|
||||||
|
result, err := db.FailPayment(ctx, sqlc.FailPaymentParams{
|
||||||
|
PaymentIdentifier: paymentHash[:],
|
||||||
|
FailReason: sqldb.SQLInt32(reason),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rowsAffected, err := result.RowsAffected()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if rowsAffected == 0 {
|
||||||
|
return ErrPaymentNotInitiated
|
||||||
|
}
|
||||||
|
|
||||||
|
payment, err := db.FetchPayment(ctx, paymentHash[:])
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fetch payment: %w", err)
|
||||||
|
}
|
||||||
|
mpPayment, err = fetchPaymentWithCompleteData(
|
||||||
|
ctx, s.cfg.QueryCfg, db, payment,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to fetch payment with "+
|
||||||
|
"complete data: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}, func() {
|
||||||
|
mpPayment = nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to fail payment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mpPayment, nil
|
||||||
|
}
|
||||||
@@ -85,6 +85,19 @@ func (q *Queries) FailAttempt(ctx context.Context, arg FailAttemptParams) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const failPayment = `-- name: FailPayment :execresult
|
||||||
|
UPDATE payments SET fail_reason = $1 WHERE payment_identifier = $2
|
||||||
|
`
|
||||||
|
|
||||||
|
type FailPaymentParams struct {
|
||||||
|
FailReason sql.NullInt32
|
||||||
|
PaymentIdentifier []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) FailPayment(ctx context.Context, arg FailPaymentParams) (sql.Result, error) {
|
||||||
|
return q.db.ExecContext(ctx, failPayment, arg.FailReason, arg.PaymentIdentifier)
|
||||||
|
}
|
||||||
|
|
||||||
const fetchAllInflightAttempts = `-- name: FetchAllInflightAttempts :many
|
const fetchAllInflightAttempts = `-- name: FetchAllInflightAttempts :many
|
||||||
SELECT
|
SELECT
|
||||||
ha.id,
|
ha.id,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ type Querier interface {
|
|||||||
DeleteUnconnectedNodes(ctx context.Context) ([][]byte, error)
|
DeleteUnconnectedNodes(ctx context.Context) ([][]byte, error)
|
||||||
DeleteZombieChannel(ctx context.Context, arg DeleteZombieChannelParams) (sql.Result, error)
|
DeleteZombieChannel(ctx context.Context, arg DeleteZombieChannelParams) (sql.Result, error)
|
||||||
FailAttempt(ctx context.Context, arg FailAttemptParams) error
|
FailAttempt(ctx context.Context, arg FailAttemptParams) error
|
||||||
|
FailPayment(ctx context.Context, arg FailPaymentParams) (sql.Result, error)
|
||||||
FetchAMPSubInvoiceHTLCs(ctx context.Context, arg FetchAMPSubInvoiceHTLCsParams) ([]FetchAMPSubInvoiceHTLCsRow, error)
|
FetchAMPSubInvoiceHTLCs(ctx context.Context, arg FetchAMPSubInvoiceHTLCsParams) ([]FetchAMPSubInvoiceHTLCsRow, error)
|
||||||
FetchAMPSubInvoices(ctx context.Context, arg FetchAMPSubInvoicesParams) ([]AmpSubInvoice, error)
|
FetchAMPSubInvoices(ctx context.Context, arg FetchAMPSubInvoicesParams) ([]AmpSubInvoice, error)
|
||||||
// Fetch all inflight attempts across all payments
|
// Fetch all inflight attempts across all payments
|
||||||
|
|||||||
@@ -352,3 +352,6 @@ VALUES (
|
|||||||
@htlc_fail_reason,
|
@htlc_fail_reason,
|
||||||
@failure_msg
|
@failure_msg
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- name: FailPayment :execresult
|
||||||
|
UPDATE payments SET fail_reason = $1 WHERE payment_identifier = $2;
|
||||||
Reference in new issue
Block a user