go-transaction-manager

module
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 15, 2024 License: MIT

README

Go transaction manager

Go Reference Test Status Coverage Status Go Report Card License

Transaction manager is an abstraction to coordinate database transaction boundaries.

Easiest way to get the perfect repository.

Supported implementations

Installation

go get github.com/avito-tech/go-transaction-manager
Backwards Compatibility

The library is compatible with the most recent two versions of Go. Compatibility beyond that is not guaranteed.

Usage

To use multiple transactions from different databases, you need to set CtxKey in Settings by WithCtxKey.

For nested transactions with different transaction managers, you need to use ChainedMW (docs).

To skip a transaction rollback due to an error, use ErrSkip or Skippable

Explanation of the approach (English, Russian)
Examples with an ideal repository and nested transactions.

Below is an example how to start usage.

package main

import (
	"context"
	"fmt"

	"github.com/jmoiron/sqlx"
	_ "github.com/mattn/go-sqlite3"

	trmsqlx "github.com/avito-tech/go-transaction-manager/sqlx"
	"github.com/avito-tech/go-transaction-manager/trm/manager"
)

func main() {
	db, err := sqlx.Open("sqlite3", "file:test?mode=memory")
	checkErr(err)
	defer db.Close()

	sqlStmt := `CREATE TABLE IF NOT EXISTS user (user_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, username TEXT);`
	_, err = db.Exec(sqlStmt)
	checkErr(err, sqlStmt)

	r := newRepo(db, trmsqlx.DefaultCtxGetter)
	ctx := context.Background()
	trManager := manager.Must(trmsqlx.NewDefaultFactory(db))
	u := &user{Username: "username"}

	err = trManager.Do(ctx, func(ctx context.Context) error {
		checkErr(r.Save(ctx, u))

		return trManager.Do(ctx, func(ctx context.Context) error {
			u.Username = "new_username"
			return r.Save(ctx, u)
		})
	})
	checkErr(err)

	userFromDB, err := r.GetByID(ctx, u.ID)
	checkErr(err)

	fmt.Println(userFromDB)
}

func checkErr(err error, args ...interface{}) {
	if err != nil {
		panic(fmt.Sprint(append([]interface{}{err}, args...)...))
	}
}

type repo struct {
	db     *sqlx.DB
	getter *trmsqlx.CtxGetter
}

func newRepo(db *sqlx.DB, c *trmsqlx.CtxGetter) *repo {
	return &repo{db: db, getter: c}
}

type user struct {
	ID       int64  `db:"user_id"`
	Username string `db:"username"`
}

func (r *repo) GetByID(ctx context.Context, id int64) (*user, error) {
	query := "SELECT * FROM user WHERE user_id = ?;"
	u := user{}

	return &u, r.getter.DefaultTrOrDB(ctx, r.db).GetContext(ctx, &u, r.db.Rebind(query), id)
}

func (r *repo) Save(ctx context.Context, u *user) error {
	query := `UPDATE user SET username = :username WHERE user_id = :user_id;`
	if u.ID == 0 {
		query = `INSERT INTO user (username) VALUES (:username);`
	}

	res, err := sqlx.NamedExecContext(ctx, r.getter.DefaultTrOrDB(ctx, r.db), r.db.Rebind(query), u)
	if err != nil {
		return err
	} else if u.ID != 0 {
		return nil
	} else if u.ID, err = res.LastInsertId(); err != nil {
		return err
	}

	return err
}

Benchmark

Comparing examples with and without trm.

Directories

Path Synopsis
drivers
goredis8 Module
gorm Module
mongo Module
pgxv4 Module
pgxv5 Module
sql Module
sqlx Module
Package gorm is an implementation of trm.Transaction interface by Transaction for *gorm.DB.
Package gorm is an implementation of trm.Transaction interface by Transaction for *gorm.DB.
internal
mock
Package mock implements dependencies for testing.
Package mock implements dependencies for testing.
Package mongo is an implementation of trm.Transaction interface by Transaction for mongo.Client.
Package mongo is an implementation of trm.Transaction interface by Transaction for mongo.Client.
Package pgxv4 is an implementation of trm.Transaction interface by Transaction for pgx.Tx.
Package pgxv4 is an implementation of trm.Transaction interface by Transaction for pgx.Tx.
Package pgxv5 is an implementation of trm.Transaction interface by Transaction for pgx.Tx.
Package pgxv5 is an implementation of trm.Transaction interface by Transaction for pgx.Tx.
Package redis is an implementation of trm.Transaction interface by Transaction for redis.UniversalClient.
Package redis is an implementation of trm.Transaction interface by Transaction for redis.UniversalClient.
sql
Package sql is an implementation of trm.Transaction interface by Transaction for sql.Tx.
Package sql is an implementation of trm.Transaction interface by Transaction for sql.Tx.
mock
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.
Package sqlx is an implementation of trm.Transaction interface by Transaction for sqlx.Tx.
Package sqlx is an implementation of trm.Transaction interface by Transaction for sqlx.Tx.
trm
Package trm contains of interfaces to programmatic transaction management.
Package trm contains of interfaces to programmatic transaction management.
context
Package context implement a setter and getter to put and get trm.Transaction from context.Context.
Package context implement a setter and getter to put and get trm.Transaction from context.Context.
drivers
Package drivers contains instruments for drivers.
Package drivers contains instruments for drivers.
manager
Package manager implements a trm.Manager interface.
Package manager implements a trm.Manager interface.
manager/mock
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.
mock
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.
settings
Package settings implements trm.Settings.
Package settings implements trm.Settings.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL