47 lines
1.2 KiB
Go
47 lines
1.2 KiB
Go
|
package db
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
|
||
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
||
|
log "github.com/sirupsen/logrus"
|
||
|
"github.com/volatiletech/sqlboiler/boil"
|
||
|
)
|
||
|
|
||
|
// TxFunc is a function that can be wrapped in a transaction
|
||
|
type TxFunc func(tx boil.Transactor) error
|
||
|
|
||
|
// WithTx wraps a function in an sql transaction. the transaction is committed if there's no error, or rolled back if there is one.
|
||
|
// if `currentTx` is nil, a new transaction is started. otherwise currentTx is used as the transaction
|
||
|
func WithTx(currentTx boil.Transactor, f TxFunc) (err error) {
|
||
|
var tx boil.Transactor
|
||
|
|
||
|
if currentTx != nil {
|
||
|
tx = currentTx
|
||
|
} else {
|
||
|
tx, err = boil.BeginTx(context.Background(), nil)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
defer func() {
|
||
|
if p := recover(); p != nil {
|
||
|
rollbackErr := tx.Rollback()
|
||
|
if rollbackErr != nil {
|
||
|
log.Errorln(errors.Prefix("rollback failed after tx error", rollbackErr))
|
||
|
}
|
||
|
panic(p)
|
||
|
} else if err != nil {
|
||
|
rollbackErr := tx.Rollback()
|
||
|
if rollbackErr != nil {
|
||
|
log.Errorln(errors.Prefix("rollback failed after tx error", rollbackErr))
|
||
|
}
|
||
|
} else {
|
||
|
err = errors.Err(tx.Commit())
|
||
|
}
|
||
|
}()
|
||
|
}
|
||
|
|
||
|
return f(tx)
|
||
|
}
|