https://github.com/moguchev/transaction_manager
Transaction manager for Golang
https://github.com/moguchev/transaction_manager
go golang nested-transactions pgx-v5 transaction transaction-manager
Last synced: 4 months ago
JSON representation
Transaction manager for Golang
- Host: GitHub
- URL: https://github.com/moguchev/transaction_manager
- Owner: moguchev
- License: gpl-3.0
- Created: 2024-11-13T19:29:30.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2024-11-14T06:07:31.000Z (7 months ago)
- Last Synced: 2024-12-02T08:47:18.916Z (6 months ago)
- Topics: go, golang, nested-transactions, pgx-v5, transaction, transaction-manager
- Language: Go
- Homepage:
- Size: 22.5 KB
- Stars: 3
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Golang Transaction Manager
[](https://goreportcard.com/report/github.com/moguchev/transaction_manager)
[](https://github.com/moguchev/transaction_manager/actions/workflows/go.yml)
[](http://godoc.org/github.com/moguchev/transaction_manager)
[](https://github.com/golang-standards/project-layout/releases/latest)Transaction manager is an abstraction to coordinate database transaction boundaries.
Easiest way to get the perfect repository.
## Supported implementations
- [pgx/v5](https://github.com/jackc/pgx)
## Installation
```sh
go get github.com/moguchev/transaction_manager
```## Usage
### Examples
- [pgx/v5](./examples/postgres/pgxv5/main.go)
Below is an example how to start usage.
1. Implement a Transaction Manager at your Repository Layer
```go
import pgxv5_transaction_manager "github.com/moguchev/transaction_manager/postgres/pgxv5"type repo struct {
driver pgxv5_transaction_manager.QueryEngineProvider // <-- add this one
}func (r *repo) Foo(ctx context.Context, v int) error {
db := r.driver.GetQueryEngine(ctx) // <-- instead of pgx.Pool/pgx.Tx direct call_, err := db.Exec(ctx, "INSERT INTO test_table_1 (id) VALUES ($1)", v)
return err
}func (r *repo) Bar(ctx context.Context, v int) error {
db := r.driver.GetQueryEngine(ctx) // <-- instead of pgx.Pool/pgx.Tx direct call_, err := db.Exec(ctx, "INSERT INTO test_table_2 (id) VALUES ($1)", v)
return err
}
```2. Use Transaction Manager in your code
```go
import "github.com/moguchev/transaction_manager"// repoInterface - your dependency
type repoInterface interface {
Foo(ctx context.Context, v int) error
Bar(ctx context.Context, v int) error
}// example - your business logic
type example struct {
transactionManager transaction_manager.TransactionManager // <-- add this onerepo repoInterface
}// Create - some usecase...
func (ex *example) Create(ctx context.Context, id int) error {
// ...transaction := func(txCtx context.Context) error { // Begin of Transaction Scope
// Foo & Bar will be called in one transaction
// (if repo supports transaction manager)if err := ex.repo.Foo(txCtx, id); err != nil {
return fmt.Errorf("foo: %w", err)
}if err := ex.repo.Bar(txCtx, id); err != nil {
return fmt.Errorf("foo: %w", err)
}return nil
} // End of Transaction Scopereturn ex.transactionManager.RunTransaction(ctx, transaction,
// additional options for out transaction without any influence on our code
// (easy to mock)
pgxv5_transaction_manager.WithAccessMode(pgx.ReadWrite),
pgxv5_transaction_manager.WithIsoLevel(pgx.ReadCommitted),
pgxv5_transaction_manager.WithDeferrableMode(pgx.Deferrable),
)
}
```3. Initialize Transaction Manager and use dependency injection to your objects
```go
func main() {
ctx := context.Background()pool, err := pgxpool.New(ctx, os.Getenv("POSTGRES_DSN"))
if err != nil {
log.Fatal(err)
}
defer pool.Close()txManager := pgxv5_transaction_manager.New(pool)
repo := &repo{
driver: txManager,
}ex := example{
repo: repo,
transactionManager: txManager,
}if err := ex.Create(ctx, 1); err != nil {
log.Fatal(err)
}
log.Println("OK")
}
```## Other projects
- [avito-tech/go-transaction-manager](https://github.com/avito-tech/go-transaction-manager)