Skip to content

williammoran/txmpg

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

txmpg

Transaction Manager support for PostgreSQL

See also: https://github.com/williammoran/txmanager

This project seeks to build a library that can be used from Golang to reliably manage transactions in PostgreSQL.

The classic example would be two banks on two different databases that need to transfer funds:

// This code is a simplified version of what's available
// in examples/bank
// The guarantee is that transfer() will complete the
// operations on BOTH accounts, or NEITHER. In no case
// will the operation be only completed on one account.
func transfer(c0 *sql.DB, a0 int, c1 *sql.DB, a1 int, amount int) {
    fmt.Printf(
        "Start transfer $%d from %d to %d\n",
        amount, a0, a1,
    )
    ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
    defer cancel()
    txm := txmanager.Transaction{}
    // It's always a good idea to defer an Abort(), if
    // the transaction was commited, Abort() is a NOOP
    defer txm.Abort("Defer")
    f0 := txmpg.NewFinalizer(ctx, "bank0", c0)
    f1 := txmpg.NewFinalizer(ctx, "bank1", c1)
    txm.Add("bank0", f0)
    txm.Add("bank1", f1)
    var avail int
    err := f0.PgTx().QueryRowContext(ctx, "SELECT balance FROM account WHERE id = $1 FOR UPDATE", a0).Scan(&avail)
    if err != nil {
        panic(err)
    }
    log.Printf("Selected balance = %d\n", avail)
    if avail < amount {
        fmt.Println("Insufficient funds")
        txm.Abort("Insufficient funds")
        panic(err)
    }
    _, err = f0.PgTx().ExecContext(ctx, "UPDATE account SET balance = balance - $1 WHERE id = $2", amount, a0)
    if err != nil {
        panic(err)
    }
    log.Println("debited balance")
    _, err = f1.PgTx().ExecContext(ctx, "UPDATE account SET balance = balance + $1 WHERE id = $2", amount, a1)
    if err != nil {
        panic(err)
    }
    log.Println("Credited balance")
    err = txm.Commit()
    if err != nil {
        panic(err)
    }
    log.Println("Transactions Comitted")
}

To try it out, see https://github.com/williammoran/txmpg/tree/master/examples/bank

About

Transaction Manager support for PostgreSQL

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages