alby-hub/transactions
Roland 5f4e52bd88
fix: publish transaction events only after the database transaction commits (#2520)
* fix: publish transaction events only after the database transaction commits

markTransactionSettled and markPaymentFailed published nwc_payment_sent /
nwc_payment_received / nwc_payment_failed (and checkBudgetUsage published
nwc_budget_warning) while still inside the caller's database transaction, so
connected apps and the Alby API could be notified of a payment whose row was
never committed, and subscribers reading the database in response to an event
could race with the commit.

Every function that writes transaction state now owns its own database
transaction and publishes its events only after the commit succeeds:

- markTransactionSettled and markPaymentFailed open their own transaction;
  callers no longer wrap them in db.Transaction
- new createSettledTransactionFromNotification inserts transactions reported
  by LNClient notifications for payments the hub has no record of (external
  payments, received keysends) directly in their settled state, removing the
  transient PENDING row and the zombie row left behind on duplicate events
- markPaymentFailed now refuses to mark a settled transaction as failed,
  replacing CancelHoldInvoice's in-transaction ACCEPTED re-check and also
  protecting the SendPaymentSync error path from a racing settle
- checkBudgetUsage returns the budget warning event instead of publishing it

Closes #2506

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: serialize payment failure with settlement and propagate lock errors

Address review findings on the previous commit:

- markPaymentFailed now takes the same payment-hash row lock as settlement
  (postgres), so the settled-state guard cannot be bypassed by a concurrent
  settle between the state check and the update; it also returns not-found
  instead of publishing an event when the transaction row no longer exists,
  and reports whether this call transitioned the row so CancelHoldInvoice
  only publishes nwc_hold_invoice_canceled when it performed the cancellation
- findSettledTransaction propagates errors from the lock query and the
  settled-transaction lookup instead of treating a failed lookup as
  "no settled transaction exists", which could defeat the dedup guard
- TestMarkSettled_Twice no longer shares one transaction struct between
  concurrent goroutines and collects errors instead of asserting inside them

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: mark failed keysend payments via markPaymentFailed

The SendKeysend failure path updated the transaction directly, which never
zeroed the fee reserve, recorded no failure reason, published no
nwc_payment_failed event, and had no guard against overwriting a
concurrently settled payment. Route it through markPaymentFailed like
SendPaymentSync, and allow MockLn keysends to fail so the path is testable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 13:38:28 +07:00
..
app_payments_test.go fix: publish transaction events only after the database transaction commits (#2520) 2026-08-08 13:38:28 +07:00
check_unsettled_transaction_test.go feat: PostgreSQL support (#922) 2025-01-16 17:17:24 +07:00
hold_invoice_self_payment_consumer.go fix: intercept self hold payments based on invoice rather than payment hash (#2027) 2026-02-27 10:22:24 +05:30
isolated_app_payments_test.go Fix: use LNClient payment context (#1728) 2025-09-16 20:53:02 +07:00
keysend_test.go fix: publish transaction events only after the database transaction commits (#2520) 2026-08-08 13:38:28 +07:00
list_transactions_test.go feat: filter transactions (#2464) 2026-08-07 10:52:14 +07:00
lookup_transaction_test.go feat: PostgreSQL support (#922) 2025-01-16 17:17:24 +07:00
make_invoice_test.go fix: add validation on MakeInvoice for zero and non-whole satoshi amounts (#2413) 2026-06-09 13:25:36 +07:00
notifications_test.go feat: filter transactions (#2464) 2026-08-07 10:52:14 +07:00
payments_test.go fix: publish transaction events only after the database transaction commits (#2520) 2026-08-08 13:38:28 +07:00
receive_keysend_test.go chore: update to use sat/msat suffixes everywhere (#2271) 2026-05-01 15:41:56 +05:30
self_hold_payments_test.go chore: update to use sat/msat suffixes everywhere (#2271) 2026-05-01 15:41:56 +05:30
self_payment_detection_test.go feat: bark backend (#2374) 2026-06-04 11:57:29 +07:00
self_payments_test.go feat: suffix balance/amount fields with explicit unit (Sat or Msat) (#2153) 2026-04-17 13:53:28 +05:30
transactions_service.go fix: publish transaction events only after the database transaction commits (#2520) 2026-08-08 13:38:28 +07:00
user_labels_test.go feat: user labels for transactions (#2265) 2026-04-30 13:13:07 +02:00