fix(db): 修复事务模式下的错误处理与回滚机制
- 在 `queryWithRetry` 和 `execWithRetry` 方法中添加对 `txFailed` 的状态管理,确保在 SQL 错误时正确标记事务失败 - 增加新的测试用例以验证事务模式下的错误处理逻辑,确保在 SQL 错误发生时能够正确回滚 - 优化测试数据库的初始化方法,支持事务测试场景
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"code.hoteas.com/golang/hotime"
|
||||
@@ -11,26 +9,6 @@ import (
|
||||
. "code.hoteas.com/golang/hotime/common"
|
||||
)
|
||||
|
||||
const debugLogPath = `d:\work\hotimev1.5\.cursor\debug.log`
|
||||
|
||||
// debugLog 写入调试日志
|
||||
func debugLog(hypothesisId, location, message string, data map[string]interface{}) {
|
||||
logFile, _ := os.OpenFile(debugLogPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if logFile != nil {
|
||||
logEntry, _ := json.Marshal(map[string]interface{}{
|
||||
"sessionId": "batch-cache-test",
|
||||
"runId": "test-run",
|
||||
"hypothesisId": hypothesisId,
|
||||
"location": location,
|
||||
"message": message,
|
||||
"data": data,
|
||||
"timestamp": time.Now().UnixMilli(),
|
||||
})
|
||||
logFile.Write(append(logEntry, '\n'))
|
||||
logFile.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// TestBatchCacheOperations 测试所有批量缓存操作
|
||||
func TestBatchCacheOperations(app *hotime.Application) {
|
||||
fmt.Println("\n========== 批量缓存操作测试开始 ==========")
|
||||
@@ -64,10 +42,6 @@ func TestBatchCacheOperations(app *hotime.Application) {
|
||||
|
||||
// testCacheMemoryBatch 测试内存缓存批量操作
|
||||
func testCacheMemoryBatch(app *hotime.Application) {
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheMemoryBatch:start", "开始测试CacheMemory批量操作", nil)
|
||||
// #endregion
|
||||
|
||||
memCache := &cache.CacheMemory{TimeOut: 3600, DbSet: true, SessionSet: true}
|
||||
memCache.SetError(&Error{})
|
||||
|
||||
@@ -79,22 +53,10 @@ func testCacheMemoryBatch(app *hotime.Application) {
|
||||
}
|
||||
memCache.CachesSet(testData)
|
||||
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheMemoryBatch:afterSet", "CacheMemory.CachesSet完成", map[string]interface{}{"count": len(testData)})
|
||||
// #endregion
|
||||
|
||||
// 测试 CachesGet
|
||||
keys := []string{"mem_key1", "mem_key2", "mem_key3", "mem_key_not_exist"}
|
||||
result := memCache.CachesGet(keys)
|
||||
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheMemoryBatch:afterGet", "CacheMemory.CachesGet完成", map[string]interface{}{
|
||||
"requested_keys": keys,
|
||||
"result_count": len(result),
|
||||
"result_keys": getMapKeys(result),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result) != 3 {
|
||||
fmt.Printf(" [FAIL] CacheMemory.CachesGet: 期望3个结果,实际%d个\n", len(result))
|
||||
} else {
|
||||
@@ -105,14 +67,6 @@ func testCacheMemoryBatch(app *hotime.Application) {
|
||||
memCache.CachesDelete([]string{"mem_key1", "mem_key2"})
|
||||
result2 := memCache.CachesGet(keys)
|
||||
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheMemoryBatch:afterDelete", "CacheMemory.CachesDelete完成", map[string]interface{}{
|
||||
"deleted_keys": []string{"mem_key1", "mem_key2"},
|
||||
"remaining_count": len(result2),
|
||||
"remaining_keys": getMapKeys(result2),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result2) != 1 || result2["mem_key3"] == nil {
|
||||
fmt.Printf(" [FAIL] CacheMemory.CachesDelete: 删除后期望1个结果,实际%d个\n", len(result2))
|
||||
} else {
|
||||
@@ -122,10 +76,6 @@ func testCacheMemoryBatch(app *hotime.Application) {
|
||||
|
||||
// testCacheDbBatch 测试数据库缓存批量操作
|
||||
func testCacheDbBatch(app *hotime.Application) {
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheDbBatch:start", "开始测试CacheDb批量操作", nil)
|
||||
// #endregion
|
||||
|
||||
// 使用应用的数据库连接
|
||||
dbCache := &cache.CacheDb{
|
||||
TimeOut: 3600,
|
||||
@@ -147,23 +97,10 @@ func testCacheDbBatch(app *hotime.Application) {
|
||||
}
|
||||
dbCache.CachesSet(testData)
|
||||
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheDbBatch:afterSet", "CacheDb.CachesSet完成", map[string]interface{}{"count": len(testData)})
|
||||
// #endregion
|
||||
|
||||
// 测试 CachesGet
|
||||
keys := []string{"db_batch_key1", "db_batch_key2", "db_batch_key3", "db_not_exist"}
|
||||
result := dbCache.CachesGet(keys)
|
||||
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheDbBatch:afterGet", "CacheDb.CachesGet完成", map[string]interface{}{
|
||||
"requested_keys": keys,
|
||||
"result_count": len(result),
|
||||
"result_keys": getMapKeys(result),
|
||||
"result_values": result,
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result) != 3 {
|
||||
fmt.Printf(" [FAIL] CacheDb.CachesGet: 期望3个结果,实际%d个\n", len(result))
|
||||
} else {
|
||||
@@ -181,14 +118,6 @@ func testCacheDbBatch(app *hotime.Application) {
|
||||
dbCache.CachesDelete([]string{"db_batch_key1", "db_batch_key2"})
|
||||
result2 := dbCache.CachesGet(keys)
|
||||
|
||||
// #region agent log
|
||||
debugLog("E", "batch_cache_test.go:testCacheDbBatch:afterDelete", "CacheDb.CachesDelete完成", map[string]interface{}{
|
||||
"deleted_keys": []string{"db_batch_key1", "db_batch_key2"},
|
||||
"remaining_count": len(result2),
|
||||
"remaining_keys": getMapKeys(result2),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result2) != 1 {
|
||||
fmt.Printf(" [FAIL] CacheDb.CachesDelete: 删除后期望1个结果,实际%d个\n", len(result2))
|
||||
} else {
|
||||
@@ -201,10 +130,6 @@ func testCacheDbBatch(app *hotime.Application) {
|
||||
|
||||
// testHoTimeCacheBatch 测试 HoTimeCache 三级缓存批量操作
|
||||
func testHoTimeCacheBatch(app *hotime.Application) {
|
||||
// #region agent log
|
||||
debugLog("D", "batch_cache_test.go:testHoTimeCacheBatch:start", "开始测试HoTimeCache三级缓存批量操作", nil)
|
||||
// #endregion
|
||||
|
||||
htCache := app.HoTimeCache
|
||||
|
||||
// 清理测试数据
|
||||
@@ -222,10 +147,6 @@ func testHoTimeCacheBatch(app *hotime.Application) {
|
||||
}
|
||||
htCache.SessionsSet(testData)
|
||||
|
||||
// #region agent log
|
||||
debugLog("D", "batch_cache_test.go:testHoTimeCacheBatch:afterSet", "HoTimeCache.SessionsSet完成", map[string]interface{}{"count": len(testData)})
|
||||
// #endregion
|
||||
|
||||
// 测试 SessionsGet
|
||||
keys := []string{
|
||||
hotime.HEAD_SESSION_ADD + "ht_batch_key1",
|
||||
@@ -235,14 +156,6 @@ func testHoTimeCacheBatch(app *hotime.Application) {
|
||||
}
|
||||
result := htCache.SessionsGet(keys)
|
||||
|
||||
// #region agent log
|
||||
debugLog("D", "batch_cache_test.go:testHoTimeCacheBatch:afterGet", "HoTimeCache.SessionsGet完成", map[string]interface{}{
|
||||
"requested_keys": len(keys),
|
||||
"result_count": len(result),
|
||||
"result_keys": getMapKeys(result),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result) != 3 {
|
||||
fmt.Printf(" [FAIL] HoTimeCache.SessionsGet: 期望3个结果,实际%d个\n", len(result))
|
||||
} else {
|
||||
@@ -256,12 +169,6 @@ func testHoTimeCacheBatch(app *hotime.Application) {
|
||||
})
|
||||
result2 := htCache.SessionsGet(keys)
|
||||
|
||||
// #region agent log
|
||||
debugLog("D", "batch_cache_test.go:testHoTimeCacheBatch:afterDelete", "HoTimeCache.SessionsDelete完成", map[string]interface{}{
|
||||
"remaining_count": len(result2),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result2) != 1 {
|
||||
fmt.Printf(" [FAIL] HoTimeCache.SessionsDelete: 删除后期望1个结果,实际%d个\n", len(result2))
|
||||
} else {
|
||||
@@ -274,10 +181,6 @@ func testHoTimeCacheBatch(app *hotime.Application) {
|
||||
|
||||
// testSessionInsBatch 测试 SessionIns 批量操作
|
||||
func testSessionInsBatch(app *hotime.Application) {
|
||||
// #region agent log
|
||||
debugLog("B", "batch_cache_test.go:testSessionInsBatch:start", "开始测试SessionIns批量操作", nil)
|
||||
// #endregion
|
||||
|
||||
// 创建一个模拟的 SessionIns
|
||||
session := &hotime.SessionIns{
|
||||
SessionId: "test_batch_session_" + ObjToStr(time.Now().UnixNano()),
|
||||
@@ -292,24 +195,9 @@ func testSessionInsBatch(app *hotime.Application) {
|
||||
}
|
||||
session.SessionsSet(testData)
|
||||
|
||||
// #region agent log
|
||||
debugLog("B", "batch_cache_test.go:testSessionInsBatch:afterSet", "SessionIns.SessionsSet完成", map[string]interface{}{
|
||||
"session_id": session.SessionId,
|
||||
"count": len(testData),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
// 测试 SessionsGet
|
||||
result := session.SessionsGet("field1", "field2", "field3", "not_exist")
|
||||
|
||||
// #region agent log
|
||||
debugLog("B", "batch_cache_test.go:testSessionInsBatch:afterGet", "SessionIns.SessionsGet完成", map[string]interface{}{
|
||||
"result_count": len(result),
|
||||
"result_keys": getMapKeys(result),
|
||||
"result": result,
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result) != 3 {
|
||||
fmt.Printf(" [FAIL] SessionIns.SessionsGet: 期望3个结果,实际%d个\n", len(result))
|
||||
} else {
|
||||
@@ -334,13 +222,6 @@ func testSessionInsBatch(app *hotime.Application) {
|
||||
session.SessionsDelete("field1", "field2")
|
||||
result2 := session.SessionsGet("field1", "field2", "field3")
|
||||
|
||||
// #region agent log
|
||||
debugLog("B", "batch_cache_test.go:testSessionInsBatch:afterDelete", "SessionIns.SessionsDelete完成", map[string]interface{}{
|
||||
"remaining_count": len(result2),
|
||||
"remaining_keys": getMapKeys(result2),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result2) != 1 {
|
||||
fmt.Printf(" [FAIL] SessionIns.SessionsDelete: 删除后期望1个结果,实际%d个\n", len(result2))
|
||||
} else {
|
||||
@@ -350,10 +231,6 @@ func testSessionInsBatch(app *hotime.Application) {
|
||||
|
||||
// testCacheBackfill 测试缓存反哺机制
|
||||
func testCacheBackfill(app *hotime.Application) {
|
||||
// #region agent log
|
||||
debugLog("D", "batch_cache_test.go:testCacheBackfill:start", "开始测试缓存反哺机制", nil)
|
||||
// #endregion
|
||||
|
||||
htCache := app.HoTimeCache
|
||||
|
||||
// 直接写入数据库缓存(绕过 memory)模拟只有 db 有数据的情况
|
||||
@@ -372,24 +249,10 @@ func testCacheBackfill(app *hotime.Application) {
|
||||
// 直接写入 db
|
||||
dbCache.Cache(testKey, testValue)
|
||||
|
||||
// #region agent log
|
||||
debugLog("D", "batch_cache_test.go:testCacheBackfill:dbWritten", "数据直接写入DB", map[string]interface{}{
|
||||
"key": testKey,
|
||||
"value": testValue,
|
||||
})
|
||||
// #endregion
|
||||
|
||||
// 通过 HoTimeCache 批量获取,应该触发反哺到 memory
|
||||
keys := []string{testKey}
|
||||
result := htCache.CachesGet(keys)
|
||||
|
||||
// #region agent log
|
||||
debugLog("D", "batch_cache_test.go:testCacheBackfill:afterGet", "HoTimeCache.CachesGet完成", map[string]interface{}{
|
||||
"result_count": len(result),
|
||||
"has_key": result[testKey] != nil,
|
||||
})
|
||||
// #endregion
|
||||
|
||||
if len(result) != 1 || result[testKey] == nil {
|
||||
fmt.Println(" [FAIL] 缓存反哺: 从 DB 读取失败")
|
||||
} else {
|
||||
@@ -402,10 +265,6 @@ func testCacheBackfill(app *hotime.Application) {
|
||||
|
||||
// testBatchEfficiency 测试批量操作效率
|
||||
func testBatchEfficiency(app *hotime.Application) {
|
||||
// #region agent log
|
||||
debugLog("A", "batch_cache_test.go:testBatchEfficiency:start", "开始测试批量操作效率", nil)
|
||||
// #endregion
|
||||
|
||||
session := &hotime.SessionIns{
|
||||
SessionId: "efficiency_test_" + ObjToStr(time.Now().UnixNano()),
|
||||
}
|
||||
@@ -423,13 +282,6 @@ func testBatchEfficiency(app *hotime.Application) {
|
||||
|
||||
batchDuration := time.Since(startTime)
|
||||
|
||||
// #region agent log
|
||||
debugLog("A", "batch_cache_test.go:testBatchEfficiency:batchSet", "批量设置完成", map[string]interface{}{
|
||||
"count": len(testData),
|
||||
"duration_ms": batchDuration.Milliseconds(),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
// 对比单个设置
|
||||
session2 := &hotime.SessionIns{
|
||||
SessionId: "efficiency_test_single_" + ObjToStr(time.Now().UnixNano()),
|
||||
@@ -442,13 +294,6 @@ func testBatchEfficiency(app *hotime.Application) {
|
||||
}
|
||||
singleDuration := time.Since(startTime2)
|
||||
|
||||
// #region agent log
|
||||
debugLog("A", "batch_cache_test.go:testBatchEfficiency:singleSet", "单个设置完成", map[string]interface{}{
|
||||
"count": 10,
|
||||
"duration_ms": singleDuration.Milliseconds(),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
fmt.Printf(" 批量设置10个字段耗时: %v\n", batchDuration)
|
||||
fmt.Printf(" 单个设置10个字段耗时: %v\n", singleDuration)
|
||||
|
||||
@@ -467,13 +312,6 @@ func testBatchEfficiency(app *hotime.Application) {
|
||||
session.SessionsGet(keys...)
|
||||
batchGetDuration := time.Since(startTime3)
|
||||
|
||||
// #region agent log
|
||||
debugLog("A", "batch_cache_test.go:testBatchEfficiency:batchGet", "批量获取完成", map[string]interface{}{
|
||||
"count": 10,
|
||||
"duration_ms": batchGetDuration.Milliseconds(),
|
||||
})
|
||||
// #endregion
|
||||
|
||||
fmt.Printf(" 批量获取10个字段耗时: %v\n", batchGetDuration)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user