-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathsqlxtransaction.go
More file actions
69 lines (55 loc) · 1.75 KB
/
sqlxtransaction.go
File metadata and controls
69 lines (55 loc) · 1.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/*
Package sqlxtransaction provides a simple way to execute a function inside an
SQLX transaction. The function to be executed is passed as an argument to the
Exec function.
For a similar functionality using the standard database/sql package instead of
the github.com/jmoiron/sqlx one, see the
github.com/Vonage/gosrvlib/pkg/sqltransaction package.
*/
package sqlxtransaction
import (
"context"
"database/sql"
"errors"
"fmt"
"github.com/Vonage/gosrvlib/pkg/logging"
"github.com/jmoiron/sqlx"
"go.uber.org/zap"
)
// ExecFunc is the type of the function to be executed inside a SQL Transaction.
type ExecFunc func(ctx context.Context, tx *sqlx.Tx) error
// DB is the interface which represents the database driver.
type DB interface {
BeginTxx(ctx context.Context, opts *sql.TxOptions) (*sqlx.Tx, error)
}
// Exec executes the specified function inside a SQL transaction.
func Exec(ctx context.Context, db DB, run ExecFunc) error {
return ExecWithOptions(ctx, db, run, nil)
}
// ExecWithOptions executes the specified function inside a SQL transaction.
func ExecWithOptions(ctx context.Context, db DB, run ExecFunc, opts *sql.TxOptions) error {
var committed bool
tx, err := db.BeginTxx(ctx, opts)
if err != nil {
return fmt.Errorf("unable to start SQLX transaction: %w", err)
}
defer func() {
if committed {
return
}
err := tx.Rollback()
if err != nil && !errors.Is(err, sql.ErrTxDone) {
logging.FromContext(ctx).Error("failed rolling back SQLX transaction", zap.Error(err))
}
}()
err = run(ctx, tx)
if err != nil {
return fmt.Errorf("failed executing a function inside SQLX transaction: %w", err)
}
err = tx.Commit()
if err != nil {
return fmt.Errorf("unable to commit SQL transaction: %w", err)
}
committed = true
return nil
}