/
executor_transaction.go
64 lines (52 loc) · 1.75 KB
/
executor_transaction.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
package wgorm
import (
"context"
"fmt"
"gorm.io/gorm"
"github.com/hanzeingithub/wgorm/log"
)
// Begin 的确把事务存在context里面要好很多,至少来说不用频繁调用delete来删除缓存中的东西,但是context会一直往下透传,也就是说这个事务也会一直透传,导致context过大
// 这种写法就不能像gorm那样支持嵌套事务部分commit了,那么只能在重复begin的时候返回相同的事务
func (e *execution) Begin(ctx context.Context) (context.Context, *gorm.DB, error) {
transaction := ctx.Value(e.transactionKey)
var tx *gorm.DB
// 防止嵌套事务,如果嵌套则返回原事务
if transaction != nil {
ctx = context.WithValue(ctx, e.reentryTransactionKey, true)
return ctx, transaction.(*gorm.DB), nil
} else {
tx = e.db.Begin()
if err := tx.Error; err != nil {
return ctx, nil, err
}
ctx = context.WithValue(ctx, e.transactionKey, tx)
}
return ctx, tx, nil
}
func (e *execution) CommitORRollback(ctx context.Context, err error, panicRecover interface{}) (context.Context, error) {
defer func() {
if panicRecover != nil {
panic(panicRecover)
}
}()
if isReentry := ctx.Value(e.reentryTransactionKey); isReentry != nil {
log.Logger.WarnOf(ctx, "reentry transaction, can't commit")
return ctx, nil
}
tx := ctx.Value(e.transactionKey)
if tx == nil {
return ctx, fmt.Errorf("commit or rollback transaction error, invaild transaction")
}
transaction := tx.(*gorm.DB)
if err != nil || panicRecover != nil {
if err = transaction.Rollback().Error; err != nil {
log.Logger.ErrorOf(ctx, "rollback error", err)
return ctx, err
}
}
if err = transaction.Commit().Error; err != nil {
log.Logger.ErrorOf(ctx, "commit error", err)
return ctx, err
}
return nil, err
}