forked from fuyibing/db
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfunc.go
108 lines (97 loc) · 2.38 KB
/
func.go
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// author: wsfuyibing <[email protected]>
// date: 2021-02-13
package db
import (
"context"
"errors"
"fmt"
"github.com/fuyibing/log/v2"
"github.com/fuyibing/log/v2/interfaces"
"github.com/kataras/iris/v12"
"xorm.io/xorm"
)
// Transaction handler.
type TransactionHandler func(ctx interface{}, sess *xorm.Session) error
// Bind context.
func Context(sess *xorm.Session, x interface{}) {
// return if nil.
if x == nil {
sess.Context(log.NewContext())
return
}
// context.Context.
if c, ok := x.(context.Context); ok && c != nil {
sess.Context(c)
return
}
// iris.Context.
if c, ok := x.(iris.Context); ok && c != nil {
if g := c.Values().Get(interfaces.OpenTracingKey); g != nil {
sess.Context(context.WithValue(context.TODO(), interfaces.OpenTracingKey, g.(interfaces.TraceInterface)))
}
return
}
}
// Return master connection.
func Master() *xorm.Session {
return Config.engines.Master().NewSession()
}
// Return master connection and bind context.
func MasterContext(ctx interface{}) *xorm.Session {
sess := Master()
Context(sess, ctx)
return sess
}
// Return slave connection.
func Slave() *xorm.Session {
if Config.slaveEnable {
return Config.engines.Slave().NewSession()
}
return Master()
}
// Return slave connection and bind context.
func SlaveContext(ctx interface{}) *xorm.Session {
sess := Slave()
Context(sess, ctx)
return sess
}
// Run transaction.
func Transaction(ctx interface{}, handlers ...TransactionHandler) (err error) {
return TransactionWithSession(ctx, nil, handlers...)
}
// Run transaction.
//
// Rollback when error return by handler, all handler executed with liner.
func TransactionWithSession(ctx interface{}, sess *xorm.Session, handlers ...TransactionHandler) (err error) {
// 1. Select master connection if session not specified.
if sess == nil {
sess = MasterContext(ctx)
}
// 2. Begin transaction.
if err = sess.Begin(); err != nil {
return
}
// 3. Defer operation.
defer func() {
// 3.1 Catch panic.
if r := recover(); r != nil {
err = errors.New(fmt.Sprintf("%v", r))
log.Errorfc(ctx, "[SQL] transaction panic: %s.", err.Error())
}
// 3.2 End transaction.
if err != nil {
// 3.2.1 rollback.
_ = sess.Rollback()
} else {
// 3.2.2 commit.
_ = sess.Commit()
}
}()
// 4. call handler by liner.
for _, handler := range handlers {
if err = handler(ctx, sess); err != nil {
break
}
}
return
}