fix: 数据库实例删除,事务问题

This commit is contained in:
meilin.huang
2024-10-30 12:17:55 +08:00
parent c1d09f447d
commit e967e02095
3 changed files with 74 additions and 27 deletions

View File

@@ -28,8 +28,8 @@
"monaco-sql-languages": "^0.12.2",
"monaco-themes": "^0.4.4",
"nprogress": "^0.2.0",
"pinia": "^2.2.4",
"qrcode.vue": "^3.5.0",
"pinia": "^2.2.5",
"qrcode.vue": "^3.5.1",
"screenfull": "^6.0.2",
"sortablejs": "^1.15.3",
"splitpanes": "^3.1.5",
@@ -58,7 +58,7 @@
"eslint": "^8.35.0",
"eslint-plugin-vue": "^9.28.0",
"prettier": "^3.2.5",
"sass": "^1.80.3",
"sass": "^1.80.5",
"typescript": "^5.6.3",
"vite": "^5.4.10",
"vue-eslint-parser": "^9.4.3"

View File

@@ -160,27 +160,46 @@ func (ai *AppImpl[T, R]) CountByCond(cond any) int64 {
return ai.GetRepo().CountByCond(cond)
}
// 执行事务操作
// Tx 执行事务操作
func (ai *AppImpl[T, R]) Tx(ctx context.Context, funcs ...func(context.Context) error) (err error) {
tx := global.Db.Begin()
dbCtx := contextx.WithDb(ctx, tx)
tx := contextx.GetTx(ctx)
dbCtx := ctx
var txDb *gorm.DB
if tx == nil {
txDb = global.Db.Begin()
dbCtx, tx = contextx.WithTxDb(ctx, txDb)
} else {
txDb = tx.DB
tx.Count++
}
defer func() {
// 移除当前已执行完成的的数据库事务实例
contextx.RmDb(ctx)
if r := recover(); r != nil {
tx.Rollback()
err = fmt.Errorf("%v", err)
txDb.Rollback()
contextx.RmDb(ctx)
err = fmt.Errorf("%v", r)
return
}
tx.Count--
if tx.Count < 1 {
// 移除当前已执行完成的的数据库事务实例
contextx.RmDb(ctx)
}
}()
for _, f := range funcs {
err = f(dbCtx)
if err != nil {
tx.Rollback()
tx.Count = 0
txDb.Rollback()
return
}
}
err = tx.Commit().Error
if tx.Count == 1 {
err = txDb.Commit().Error
}
return
}

View File

@@ -49,28 +49,56 @@ func GetTraceId(ctx context.Context) string {
return ""
}
// 将事务db放置context中使用stack保存。以便多个方法调用实现方法内部各自的事务操作
func WithDb(ctx context.Context, db *gorm.DB) context.Context {
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*gorm.DB]); ok {
dbStack.Push(db)
return ctx
}
dbStack := new(collx.Stack[*gorm.DB])
dbStack.Push(db)
return context.WithValue(ctx, DbKey, dbStack)
// Tx 事务上下文信息
type Tx struct {
Count int
DB *gorm.DB
}
// 获取当前操作的栈顶事务数据库实例
func (t *Tx) Rollback() {
if t.Count == 0 {
t.DB.Rollback()
} else {
}
}
// WithTxDb 将事务db放置context中使用stack保存。以便多个方法调用实现方法内部各自的事务操作
func WithTxDb(ctx context.Context, db *gorm.DB) (context.Context, *Tx) {
tx := &Tx{Count: 1, DB: db}
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
dbStack.Push(tx)
return ctx, tx
}
dbStack := new(collx.Stack[*Tx])
dbStack.Push(tx)
return context.WithValue(ctx, DbKey, dbStack), tx
}
// GetDb 获取当前操作的栈顶事务数据库实例
func GetDb(ctx context.Context) *gorm.DB {
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*gorm.DB]); ok {
return dbStack.Top()
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
if tx := dbStack.Top(); tx != nil {
return tx.DB
}
}
return nil
}
func RmDb(ctx context.Context) *gorm.DB {
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*gorm.DB]); ok {
// GetTx 获取当前操作的栈顶事务信息
func GetTx(ctx context.Context) *Tx {
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
if tx := dbStack.Top(); tx != nil {
return tx
}
}
return nil
}
// RmDb 删除数据库事务db
func RmDb(ctx context.Context) *Tx {
if dbStack, ok := ctx.Value(DbKey).(*collx.Stack[*Tx]); ok {
return dbStack.Pop()
}
return nil