Skip to content

fix!: Execute queries inside a Transaction#18

Merged
ValuedMammal merged 2 commits intobitcoindevkit:masterfrom
ValuedMammal:fix/sqlx_transaction
May 1, 2026
Merged

fix!: Execute queries inside a Transaction#18
ValuedMammal merged 2 commits intobitcoindevkit:masterfrom
ValuedMammal:fix/sqlx_transaction

Conversation

@ValuedMammal
Copy link
Copy Markdown
Collaborator

Fixes #17

Description

Every write path previously executed N individual SQL statements directly against the connection pool, each running in its own implicit auto-commit transaction. If any statement failed mid-way, the database was left in a partially-applied state, e.g. a ChangeSet whose tx_graph was written but whose local_chain was not.

This PR wraps all writes in an explicit BEGIN / COMMIT transaction so that a ChangeSet either lands completely or not at all.

Notes to the reviewers

wallet: Store::write_changeset now opens a single sqlx transaction and threads it through every write method (write_network, write_keychain_descriptors, write_local_chain, write_tx_graph, write_keychain_txout, write_locked_outpoints). The transaction is committed only after all writes succeed; any error causes an implicit rollback.

async_store: The lower-level write methods (write_tx_graph, write_local_chain, write_keychain_txout) and their read counterparts now accept conn: &mut SqliteConnection rather than operating on &self.pool. This makes them usable inside a caller-owned transaction without leaking transaction management concerns into the individual methods.

The performance improvement is a secondary benefit. SQLite still amortises WAL-frame overhead across the single COMMIT, reducing internal bookkeeping compared to N auto-commit boundaries.

Changelog

BREAKING — all lower-level read/write methods that previously took &self are now member functions accepting conn: &mut SqliteConnection. Callers who invoked these directly must now supply a connection or transaction handle.

async_store:

  • Store::write_tx_graph
  • Store::write_local_chain
  • Store::write_keychain_txout
  • Store::read_tx_graph
  • Store::read_local_chain
  • Store::read_keychain_txout

wallet:

  • Store::write_network
  • Store::write_keychain_descriptors
  • Store::write_locked_outpoints
  • Store::read_network
  • Store::read_keychain_descriptors
  • Store::read_locked_outpoints

The high-level entry points Store::write_changeset and Store::read_changeset are unchanged and remain the recommended API.

The wallet now begins a transaction before reading/
writing the ChangeSet and only commits after all queries
have succeeded. This makes database operations atomic by
preventing partial writes and improves performance by
flushing all queries to the database at once.

BREAKING:

Low level async Store functions are changed to accept
`&mut Connection` as parameter.
@ValuedMammal ValuedMammal merged commit d7cfe7a into bitcoindevkit:master May 1, 2026
3 checks passed
@ValuedMammal ValuedMammal deleted the fix/sqlx_transaction branch May 1, 2026 18:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Execute queries inside a sqlx Transaction

1 participant