Helper function for transaction
manishtomar opened this issue · comments
Hello, Would you be willing to accept a helper function that executes a given function inside a transaction and automatically commits or rollbacks based on function return? This is how function will be used:
sess := conn.NewSession(nil)
return sess.WithTransaction(ctx, func(tx *dbr.Tx) error {
if err = tx.Update(); err != nil {
return err
}
...
return nil
})
WithTransaction
starts a transaction and calls do
with the transaction object. If do
returns nil then transaction is committed, otherwise it is rolled back and original error occurring in do
is returned. If returned error is special value ErrRollback
then WithTransaction
returns nil
. This gives consumers to decide whether to rollback or not. I've currently implemented this internally and this is how it looks:
// withTransaction starts a transaction with given fields and executes the function within that transaction.
// Transaction is committed only if function returns nil. If it returns non-nil error then it is
// rolled back. However, if returned error is errRollback then withTransaction returns nil after
// successfully rolling back
func withTransaction(ctx context.Context, do func(tx *dbr.Tx) error) error {
sess := pg.conn.NewSession()
tx, err := sess.BeginTx(ctx, nil)
if err != nil {
return err
}
err = do(tx)
if err != nil {
// function errored. rollback either way
rberr := tx.Rollback()
if rberr != nil && rberr != sql.ErrTxDone {
// log the original function error since we will lose it here when wrapping rollback error
logger.WithError(err).Error("Error from withTransaction function")
return rberr
}
if err == errRollback {
// function intended to rollback, hence return success after successfully rolling back
return nil
}
// return original error after successfully rolling back
return err
}
err = tx.Commit()
if err != nil && err != sql.ErrTxDone {
return err
}
return nil
}
LMK if this looks good and I'll create a PR with this. Thanks for a great library!
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
@taylorchu Can you please have a look at above recommendation? I'll be happy to open a PR if you are ok to review and merge it. Thanks!
yes. lgtm 👍
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.