https://github.com/ysomad/pgxatomic
Transaction manager for pgx
https://github.com/ysomad/pgxatomic
clean-architecture go golang hexagonal-architecture pgx postgresql transactions
Last synced: 5 months ago
JSON representation
Transaction manager for pgx
- Host: GitHub
- URL: https://github.com/ysomad/pgxatomic
- Owner: ysomad
- License: mit
- Created: 2022-10-30T18:38:45.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2025-11-01T14:31:11.000Z (7 months ago)
- Last Synced: 2025-11-01T16:14:50.902Z (7 months ago)
- Topics: clean-architecture, go, golang, hexagonal-architecture, pgx, postgresql, transactions
- Language: Go
- Homepage:
- Size: 26.4 KB
- Stars: 11
- Watchers: 1
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# pgxatomic
A library for managing PostgreSQL transactions through context propagation using the [pgx](https://github.com/jackc/pgx) driver.
pgxatomic allows you to pass transactions via `context.Context`, providing cleaner separation between business logic and transaction management. Repository and service layers work with contexts while transaction boundaries are controlled at higher levels.

## Installation
```bash
go get github.com/ysomad/pgxatomic
```
## Usage
### Repository layer
Use `pgxatomic.Pool` in your repository. It wraps `pgxpool.Pool` and automatically uses transactions from context when available.
```go
type orderRepo struct {
pool *pgxatomic.Pool
}
type order struct {
ID uuid.UUID
Cost int
}
func (r *orderRepo) Insert(ctx context.Context, cost int) order {
rows, _ := r.pool.Query(ctx, "INSERT INTO orders(cost) VALUES ($1) RETURNING id, cost", cost)
o, _ := pgx.CollectOneRow(rows, pgx.RowToStructByPos[order])
return o
}
```
Alternatively, use `Query`, `QueryRow`, and `Exec` functions directly without the pool wrapper.
### Transaction management
Use `Runner` to execute operations within a transaction. The transaction propagates automatically through context.
```go
conf, _ := pgxpool.ParseConfig("postgres://user:pass@localhost:5432/postgres")
pool, _ := pgxpool.NewWithConfig(context.Background(), conf)
runner, _ := pgxatomic.NewRunner(pool, pgx.TxOptions{})
_ = runner.Run(context.Background(), func(txCtx context.Context) error {
_ = orderService.Create(txCtx)
_ = balanceService.Withdraw(txCtx)
return nil
})
```
All operations within `Run` use the same transaction. If the function returns an error, the transaction rolls back. Otherwise, it commits.
Note: Error handling is omitted for brevity. Handle errors appropriately in production code.
## References
- [Clean transactions in Golang hexagon](https://www.kaznacheev.me/posts/en/clean-transactions-in-hexagon)