package main import ( "encoding/json" "fmt" "os" "time" "code.hoteas.com/golang/hotime" "code.hoteas.com/golang/hotime/cache" . "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========== 批量缓存操作测试开始 ==========") // 测试1: 测试 CacheMemory 批量操作 fmt.Println("\n--- 测试1: CacheMemory 批量操作 ---") testCacheMemoryBatch(app) // 测试2: 测试 CacheDb 批量操作 fmt.Println("\n--- 测试2: CacheDb 批量操作 ---") testCacheDbBatch(app) // 测试3: 测试 HoTimeCache 三级缓存批量操作 fmt.Println("\n--- 测试3: HoTimeCache 三级缓存批量操作 ---") testHoTimeCacheBatch(app) // 测试4: 测试 SessionIns 批量操作 fmt.Println("\n--- 测试4: SessionIns 批量操作 ---") testSessionInsBatch(app) // 测试5: 测试缓存反哺机制 fmt.Println("\n--- 测试5: 缓存反哺机制测试 ---") testCacheBackfill(app) // 测试6: 测试批量操作效率(一次性写入验证) fmt.Println("\n--- 测试6: 批量操作效率测试 ---") testBatchEfficiency(app) fmt.Println("\n========== 批量缓存操作测试完成 ==========") } // 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{}) // 测试 CachesSet testData := Map{ "mem_key1": "value1", "mem_key2": "value2", "mem_key3": "value3", } 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 { fmt.Println(" [PASS] CacheMemory.CachesGet: 批量获取正确") } // 测试 CachesDelete 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 { fmt.Println(" [PASS] CacheMemory.CachesDelete: 批量删除正确") } } // 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, DbSet: true, SessionSet: true, Mode: cache.CacheModeNew, Db: &app.Db, } dbCache.SetError(&Error{}) // 清理测试数据 dbCache.CachesDelete([]string{"db_batch_key1", "db_batch_key2", "db_batch_key3"}) // 测试 CachesSet testData := Map{ "db_batch_key1": "db_value1", "db_batch_key2": "db_value2", "db_batch_key3": "db_value3", } 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 { fmt.Println(" [PASS] CacheDb.CachesGet: 批量获取正确") } // 验证值正确性 if result["db_batch_key1"] != "db_value1" { fmt.Printf(" [FAIL] CacheDb.CachesGet: db_batch_key1 值不正确,期望 db_value1,实际 %v\n", result["db_batch_key1"]) } else { fmt.Println(" [PASS] CacheDb.CachesGet: 值内容正确") } // 测试 CachesDelete 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 { fmt.Println(" [PASS] CacheDb.CachesDelete: 批量删除正确") } // 清理 dbCache.CachesDelete([]string{"db_batch_key3"}) } // testHoTimeCacheBatch 测试 HoTimeCache 三级缓存批量操作 func testHoTimeCacheBatch(app *hotime.Application) { // #region agent log debugLog("D", "batch_cache_test.go:testHoTimeCacheBatch:start", "开始测试HoTimeCache三级缓存批量操作", nil) // #endregion htCache := app.HoTimeCache // 清理测试数据 htCache.SessionsDelete([]string{ hotime.HEAD_SESSION_ADD + "ht_batch_key1", hotime.HEAD_SESSION_ADD + "ht_batch_key2", hotime.HEAD_SESSION_ADD + "ht_batch_key3", }) // 测试 SessionsSet testData := Map{ hotime.HEAD_SESSION_ADD + "ht_batch_key1": Map{"user": "test1", "role": "admin"}, hotime.HEAD_SESSION_ADD + "ht_batch_key2": Map{"user": "test2", "role": "user"}, hotime.HEAD_SESSION_ADD + "ht_batch_key3": Map{"user": "test3", "role": "guest"}, } 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", hotime.HEAD_SESSION_ADD + "ht_batch_key2", hotime.HEAD_SESSION_ADD + "ht_batch_key3", hotime.HEAD_SESSION_ADD + "ht_not_exist", } 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 { fmt.Println(" [PASS] HoTimeCache.SessionsGet: 批量获取正确") } // 测试 SessionsDelete htCache.SessionsDelete([]string{ hotime.HEAD_SESSION_ADD + "ht_batch_key1", hotime.HEAD_SESSION_ADD + "ht_batch_key2", }) 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 { fmt.Println(" [PASS] HoTimeCache.SessionsDelete: 批量删除正确") } // 清理 htCache.SessionsDelete([]string{hotime.HEAD_SESSION_ADD + "ht_batch_key3"}) } // 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()), } session.Init(app.HoTimeCache) // 测试 SessionsSet testData := Map{ "field1": "value1", "field2": 123, "field3": Map{"nested": "data"}, } 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 { fmt.Println(" [PASS] SessionIns.SessionsGet: 批量获取正确") } // 验证值类型 if result["field1"] != "value1" { fmt.Printf(" [FAIL] SessionIns.SessionsGet: field1 值不正确\n") } else { fmt.Println(" [PASS] SessionIns.SessionsGet: 字符串值正确") } var convErr Error if ObjToInt(result["field2"], &convErr) != 123 { fmt.Printf(" [FAIL] SessionIns.SessionsGet: field2 值不正确\n") } else { fmt.Println(" [PASS] SessionIns.SessionsGet: 数值类型正确") } // 测试 SessionsDelete 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 { fmt.Println(" [PASS] SessionIns.SessionsDelete: 批量删除正确") } } // testCacheBackfill 测试缓存反哺机制 func testCacheBackfill(app *hotime.Application) { // #region agent log debugLog("D", "batch_cache_test.go:testCacheBackfill:start", "开始测试缓存反哺机制", nil) // #endregion htCache := app.HoTimeCache // 直接写入数据库缓存(绕过 memory)模拟只有 db 有数据的情况 dbCache := &cache.CacheDb{ TimeOut: 3600, DbSet: true, SessionSet: true, Mode: cache.CacheModeNew, Db: &app.Db, } dbCache.SetError(&Error{}) testKey := "backfill_test_key_" + ObjToStr(time.Now().UnixNano()) testValue := Map{"backfill": "test_data"} // 直接写入 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 { fmt.Println(" [PASS] 缓存反哺: 从 DB 读取成功") } // 清理 htCache.CachesDelete(keys) } // 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()), } session.Init(app.HoTimeCache) // 记录批量设置开始时间 startTime := time.Now() // 设置10个字段 testData := Map{} for i := 0; i < 10; i++ { testData[fmt.Sprintf("eff_field_%d", i)] = fmt.Sprintf("value_%d", i) } session.SessionsSet(testData) 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()), } session2.Init(app.HoTimeCache) startTime2 := time.Now() for i := 0; i < 10; i++ { session2.Session(fmt.Sprintf("single_field_%d", i), fmt.Sprintf("value_%d", i)) } 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) if batchDuration < singleDuration { fmt.Println(" [PASS] 批量操作效率: 批量操作更快") } else { fmt.Println(" [WARN] 批量操作效率: 批量操作未体现优势(可能数据量太小)") } // 批量获取测试 startTime3 := time.Now() keys := make([]string, 10) for i := 0; i < 10; i++ { keys[i] = fmt.Sprintf("eff_field_%d", i) } 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) } // getMapKeys 获取 Map 的所有键 func getMapKeys(m Map) []string { keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } return keys }