MCPcopy Index your code
hub / github.com/avito-tech/go-transaction-manager

github.com/avito-tech/go-transaction-manager @v1.5.1

Chat with this repo
repository ↗ · DeepWiki ↗ · release v1.5.1 ↗ · + Follow
958 symbols 3,026 edges 140 files 363 documented · 38% updated 5d ago★ 4121 open issues
What it actually does AI analysis from the code graph — generated when you open this
loading…
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.

Extension points exported contracts — how you extend this code

NestedTrFactory (Interface)
NestedTrFactory creates nested Transaction. [9 implementers]
trm/transaction.go
UserRepo (Interface)
(no doc) [14 implementers]
internal/example/habr/init/domain/repository.go
Settings (Interface)
Settings is the configuration of the Manager. Preferable to implement as an immutable struct. settings.Settings is a de [4 …
trm/settings.go
Manager (Interface)
Manager manages a transaction from Begin to Commit or Rollback. [4 implementers]
trm/manager.go
SavePoint (Interface)
This file copies an interface from https://github.com/DATA-DOG/go-txdb SavePoint defines the syntax to create savepoints [3 …
sql/savepoint.go
CtxManager (Interface)
CtxManager sets and gets a Transaction in/from context.Context. [1 implementers]
trm/context.go
Watch (Interface)
Watch is experimental functional for watching updated keys. See redis_test.Example_watch for example. [1 implementers]
redis/watcher.go
Tr (Interface)
Tr is an interface to work with sql.DB or sql.Tx. StmtContext and Stmt are not implemented!
sql/contract.go

Core symbols most depended-on inside this repo

Must
called by 112
trm/settings/settings.go
Do
called by 51
trm/manager.go
Close
called by 48
trm/drivers/is_closed.go
IsActive
called by 46
trm/transaction.go
WithCancelable
called by 43
trm/settings/option.go
WithPropagation
called by 38
trm/settings/option.go
Save
called by 32
internal/example/habr/finished/domain/repository.go
Return
called by 32
redis/settings.go

Shape

Method 462
Function 305
Struct 139
Interface 27
FuncType 16
TypeAlias 9

Languages

Go100%

Modules by API surface

redis/readonly_func_without_tx_test.go69 symbols
redis/readonly_func_without_tx.go69 symbols
trm/mock/transaction.go36 symbols
trm/mock/settings.go28 symbols
trm/settings/settings.go21 symbols
redis/settings.go20 symbols
trm/manager/struct_test.go17 symbols
sqlx/contract.go16 symbols
trm/manager/chain.go14 symbols
redis/example_test.go14 symbols
trm/transaction.go13 symbols
trm/settings.go13 symbols

Datastores touched

usersCollection · 1 repos
(mongodb)Database · 1 repos

For agents

$ claude mcp add go-transaction-manager \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page