You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add a transaction runner for a plain database handle #80
It begins a transaction, runs body, commits when body succeeds and rolls back otherwise, also when body panics or the commit fails.
Why
Two stores already carry their own copy of the same few lines:
gouncer's authkit/sqlite store (inTx in store.go)
Gophenberg's SQLite site settings store (internal/sqlite/tx.go)
Each copy has to get the deferred rollback right. If one forgets it, a failed write on SQLite keeps the file's write lock until its context ends, and every later writer then waits and fails as busy. One tested runner in dbkit removes that risk for every caller. Laravel (DB::transaction), Rails (ActiveRecord::Base.transaction) and Django (transaction.atomic) all keep this helper in the framework for the same reason.
dbkit.Share already has Begin. The runner could sit beside it, or take the share as well as a plain handle.
I can take this. I will add a small dbkit.InTx helper for plain *sql.DB handles, with tests covering commit, rollback on body error, and panic cleanup.
One more thing the runner should do: report a rollback that fails. Both copies today drop it with defer func() { _ = tx.Rollback() }(). After a successful commit, Rollback returns sql.ErrTxDone, which is expected. After a failed body, any other rollback error should be joined to the body's error, for example with errors.Join, so the caller sees both.
The product cannot test this today, because sqlitetest.Faults can fail a statement or a commit but not a rollback. A FailNextRollback beside FailNextCommit would let dbkit pin it.
Activity
KeuqS commentedon Oct 14, 2026
I can take this. I will add a small dbkit.InTx helper for plain *sql.DB handles, with tests covering commit, rollback on body error, and panic cleanup.
KeuqS commentedon Oct 14, 2026
Implementation is ready in PR #82: #82. It adds
dbkit.InTxwith commit, rollback, and panic-cleanup tests.SirLouen commentedon Oct 14, 2026
One more thing the runner should do: report a rollback that fails. Both copies today drop it with
defer func() { _ = tx.Rollback() }(). After a successful commit,Rollbackreturnssql.ErrTxDone, which is expected. After a failed body, any other rollback error should be joined to the body's error, for example witherrors.Join, so the caller sees both.The product cannot test this today, because
sqlitetest.Faultscan fail a statement or a commit but not a rollback. AFailNextRollbackbesideFailNextCommitwould let dbkit pin it.