a simple pgx transaction manager that automatically rolls back on error.
supports timeouts and read-only transactions.
NewTxnProvider returns a transaction manager and a function to get a connection from the pool.
func main() {
ctx := context.Background()
pool, err := pgxpool.New(ctx, "postgres://user:pass@localhost:5432/db")
if err != nil {
panic(err)
}
defer pool.Close()
txnManager, getConn := gollback.NewTxnProvider(pool)
} replace pgxpool.Pool in your repositories with getConn
type UserRepo struct {
db getConn
}
func (r *UserRepo) GetByID(ctx context.Contex, id int) (*User, error) {
return r.db.QueryRow(ctx, "SELECT * FROM users WHERE id = $1", id)
}your services can now use the transaction manager to string together multiple repository calls into a single transaction.
type Service struct {
userRepo UserRepo
postRepo PostRepo
txnManager gollback.TxnManager
}
func (s *Service) CreatePost(ctx context.Context, userID int, post *Post) error {
return s.txnManager.RunInTxn(ctx, func(ctx context.Context) error {
_, err := s.userRepo.GetByID(ctx, UserID)
if err != nil {
return err
}
_, err = s.postRepo.Create(ctx, post, user.Name)
if err != nil {
return err
}
return nil
}
}- the transaction is rolled back if the function returns an error
- the transaction is committed if the function returns nil
s.txnManager.RunInTxn(ctx, func(ctx context.Context) error {
return s.userRepo.GetByID(ctx, 123)
}, gollback.WithTimeout(5*time.Second))Important
the timeout cancels in-progress database operations and prevents commits but does not forcibly terminate your function. If your function has long-running computations between database calls, the transaction will remain open until the function completes. For early exit, check ctx.Done() periodically.
s.txnManager.RunInTxn(ctx, func(ctx context.Context) error {
return s.userRepo.GetByID(ctx, 123)
}, gollback.ReadOnly())the above functional options can be combined.
the following typed errors are returned by the transaction manager:
gollback.TxnBeginErrorgollback.TxnCommitErrorgollback.TxnRollbackError- the original error is available via
.Cause
- the original error is available via