refactor(db): 增强测试事务支持和保存点管理
- 在 HoTimeDB 中新增测试事务功能,允许在测试模式下使用事务进行操作 - 实现 BeginTestTx 和 RollbackTestTx 方法,支持测试事务的开启和回滚 - 在 Action 方法中集成保存点管理,确保在测试模式下的嵌套事务处理 - 更新 README.md,添加 API 测试框架的相关说明,提升文档完整性
This commit is contained in:
@@ -32,6 +32,7 @@ type HoTimeDB struct {
|
||||
mu sync.RWMutex
|
||||
limitMu sync.Mutex
|
||||
Dialect Dialect // 数据库方言适配器
|
||||
testTx *sql.Tx // 测试事务:设置后所有操作都在此事务内,测试结束回滚
|
||||
}
|
||||
|
||||
// SetConnect 设置数据库配置连接
|
||||
@@ -145,3 +146,23 @@ func trimQuotes(s string) string {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// BeginTestTx 开启测试事务,设置后所有 Query/Exec/Action 都在此事务内执行
|
||||
func (that *HoTimeDB) BeginTestTx() error {
|
||||
tx, err := that.DB.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
that.testTx = tx
|
||||
return nil
|
||||
}
|
||||
|
||||
// RollbackTestTx 回滚测试事务,清除 testTx 状态
|
||||
func (that *HoTimeDB) RollbackTestTx() error {
|
||||
if that.testTx != nil {
|
||||
err := that.testTx.Rollback()
|
||||
that.testTx = nil
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
+6
-2
@@ -61,7 +61,9 @@ func (that *HoTimeDB) queryWithRetry(query string, retried bool, args ...interfa
|
||||
// 处理参数中的 slice 类型
|
||||
processedArgs := that.processArgs(args)
|
||||
|
||||
if that.Tx != nil {
|
||||
if that.testTx != nil {
|
||||
resl, err = that.testTx.Query(query, processedArgs...)
|
||||
} else if that.Tx != nil {
|
||||
resl, err = that.Tx.Query(query, processedArgs...)
|
||||
} else {
|
||||
resl, err = db.Query(query, processedArgs...)
|
||||
@@ -117,7 +119,9 @@ func (that *HoTimeDB) execWithRetry(query string, retried bool, args ...interfac
|
||||
// 处理参数中的 slice 类型
|
||||
processedArgs := that.processArgs(args)
|
||||
|
||||
if that.Tx != nil {
|
||||
if that.testTx != nil {
|
||||
resl, e = that.testTx.Exec(query, processedArgs...)
|
||||
} else if that.Tx != nil {
|
||||
resl, e = that.Tx.Exec(query, processedArgs...)
|
||||
} else {
|
||||
resl, e = that.DB.Exec(query, processedArgs...)
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
var savepointCounter uint64
|
||||
|
||||
// Action 事务操作
|
||||
// 如果 action 返回 true 则提交事务;返回 false 则回滚
|
||||
// 测试模式下(testTx != nil),使用 SAVEPOINT 代替真事务,确保嵌套事务不会绕过外层测试事务
|
||||
func (that *HoTimeDB) Action(action func(db HoTimeDB) (isSuccess bool)) (isSuccess bool) {
|
||||
db := HoTimeDB{
|
||||
DB: that.DB,
|
||||
@@ -26,6 +31,20 @@ func (that *HoTimeDB) Action(action func(db HoTimeDB) (isSuccess bool)) (isSucce
|
||||
Dialect: that.Dialect,
|
||||
mu: sync.RWMutex{},
|
||||
limitMu: sync.Mutex{},
|
||||
testTx: that.testTx,
|
||||
}
|
||||
|
||||
if that.testTx != nil {
|
||||
spName := fmt.Sprintf("sp_%d", atomic.AddUint64(&savepointCounter, 1))
|
||||
_, _ = that.testTx.Exec("SAVEPOINT " + spName)
|
||||
db.Tx = that.testTx
|
||||
isSuccess = action(db)
|
||||
if !isSuccess {
|
||||
_, _ = that.testTx.Exec("ROLLBACK TO SAVEPOINT " + spName)
|
||||
} else {
|
||||
_, _ = that.testTx.Exec("RELEASE SAVEPOINT " + spName)
|
||||
}
|
||||
return isSuccess
|
||||
}
|
||||
|
||||
tx, err := db.Begin()
|
||||
|
||||
Reference in New Issue
Block a user