2020-06-16 05:37:51 +02:00
|
|
|
package db
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/lbryio/lbry.go/v2/extras/errors"
|
|
|
|
log "github.com/sirupsen/logrus"
|
2023-05-30 18:17:46 +02:00
|
|
|
"github.com/volatiletech/sqlboiler/v4/boil"
|
2020-06-16 05:37:51 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
}
|