Files
x/database/transactor.go
Colin Henry 54aae5f242
All checks were successful
Go / build (1.23) (push) Successful in 3m51s
big updates: tests, bug fixed, documentation. oh my
2026-01-03 15:53:50 -08:00

41 lines
1.0 KiB
Go

package database
import (
"context"
"database/sql"
"fmt"
)
// WithinTransaction wraps a database function to execute within a transaction.
// It begins a transaction, executes the function, and commits on success or rolls back on error.
//
// This is a functional equivalent of the Transactor interface pattern described by Thibaut Rousseau:
// https://blog.thibaut-rousseau.com/blog/sql-transactions-in-go-the-good-way/
//
// Example:
//
// insert := func(ctx context.Context, db *sql.DB) error {
// _, err := db.ExecContext(ctx, "INSERT INTO users (...) VALUES (...)")
// return err
// }
// actor.ActionChan <- WithinTransaction(insert)
func WithinTransaction(f Func) Func {
return func(ctx context.Context, db *sql.DB) error {
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return fmt.Errorf("failed to begin transaction: %w", err)
}
if err := f(ctx, db); err != nil {
_ = tx.Rollback()
return err
}
if err := tx.Commit(); err != nil {
return fmt.Errorf("failed to commit transaction: %w", err)
}
return nil
}
}