Manager: log an error when database rollback fails

Log an error when a database transaction rollback fails. I wouldn't know
how to test, because usually stuff Just Works, but it's good to have
this logged anyway.
This commit is contained in:
Sybren A. Stüvel 2025-03-20 13:32:29 +01:00
parent 5706fe435a
commit f1de595acc

View File

@ -6,6 +6,7 @@ package persistence
import ( import (
"context" "context"
"database/sql" "database/sql"
"errors"
"fmt" "fmt"
"time" "time"
@ -163,7 +164,7 @@ func (db *DB) queries() *sqlc.Queries {
type queriesTX struct { type queriesTX struct {
queries *sqlc.Queries queries *sqlc.Queries
commit func() error commit func() error
rollback func() error rollback func()
} }
// queries returns the SQLC Queries struct, connected to this database. // queries returns the SQLC Queries struct, connected to this database.
@ -182,12 +183,29 @@ func (db *DB) queriesWithTX() (*queriesTX, error) {
qtx := queriesTX{ qtx := queriesTX{
queries: sqlc.New(&loggingWrapper), queries: sqlc.New(&loggingWrapper),
commit: tx.Commit, commit: tx.Commit,
rollback: tx.Rollback, rollback: rollbackWrapper(tx.Rollback),
} }
return &qtx, nil return &qtx, nil
} }
func rollbackWrapper(rollback func() error) func() {
return func() {
err := rollback()
// AThis function is typically called unconditionally via `defer` and so the
// most common case is that the transaction has already been committed, and
// thus ErrTxDone is returned here.
switch {
case err == nil: // Not really expected, but a good rollback is ok.
case errors.Is(err, sql.ErrTxDone): // Expected.
default:
log.Error().Msg("database: query rollback failed unexpectedly")
}
}
}
// now returns 'now' as reported by db.nowfunc. // now returns 'now' as reported by db.nowfunc.
// It always converts the timestamp to UTC. // It always converts the timestamp to UTC.
func (db *DB) now() time.Time { func (db *DB) now() time.Time {