package middleware import ( "context" "fmt" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" ) // TransactionManager handles database transactions type TransactionManager struct { pool *pgxpool.Pool } // NewTransactionManager creates a new transaction manager func NewTransactionManager(pool *pgxpool.Pool) *TransactionManager { return &TransactionManager{pool: pool} } // WithTx runs a function within a database transaction // If the function returns an error, the transaction is rolled back // If the function succeeds, the transaction is committed func (tm *TransactionManager) WithTx(ctx context.Context, fn func(pgx.Tx) error) error { tx, err := tm.pool.Begin(ctx) if err != nil { return fmt.Errorf("failed to begin transaction: %w", err) } // Ensure the transaction is handled properly defer func() { if p := recover(); p != nil { // A panic occurred, rollback and re-panic _ = tx.Rollback(ctx) panic(p) } }() if err := fn(tx); err != nil { // Function returned error, rollback if rbErr := tx.Rollback(ctx); rbErr != nil { return fmt.Errorf("function error: %v, rollback error: %w", err, rbErr) } return err } // Success, commit if err := tx.Commit(ctx); err != nil { return fmt.Errorf("failed to commit transaction: %w", err) } return nil }