✨ feat(cache): 幂等只读接口接入缓存
- 新增 withCache 包装:命中直接返回,miss 回源后写入,仅缓存成功响应 - 详情/目录/批量详情/章节摘要缓存 24 小时;搜索/分类列表/分类详情短缓存 10 分钟 - 7 个 fqapi 处理函数原函数体不动、改名 fetchXxx,外层套缓存壳 - redisGetCache 补 3 秒读超时,与写路径一致,防远程 Redis 网络抖动拖垮请求 - 新增 TestWithCache:验证命中不回源、失败响应不缓存
This commit is contained in:
1 parent
f0d89b462b
commit
586b714f3c
10 files changed
+109
-8
No files matched your search
@@ -55,3 +55,46 @@ func TestConcurrentCacheAccess(t *testing.T) {
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// TestWithCache 验证缓存命中不回源、失败响应不缓存
|
||||
func TestWithCache(t *testing.T) {
|
||||
if err := config.LoadConfig("../../config/config.yaml"); err != nil {
|
||||
t.Skipf("无法加载配置: %v", err)
|
||||
}
|
||||
db, err := sql.Open("sqlite3", t.TempDir()+"/test.db?_journal_mode=WAL&_busy_timeout=5000")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
oldDB, oldDriver := cacheDB, dbDriver
|
||||
cacheDB, dbDriver = db, "sqlite3"
|
||||
defer func() {
|
||||
cacheDB, dbDriver = oldDB, oldDriver
|
||||
db.Close()
|
||||
}()
|
||||
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS cache (
|
||||
key TEXT PRIMARY KEY, value TEXT,
|
||||
created_at INTEGER DEFAULT (strftime('%s', 'now'))
|
||||
)`); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
calls := 0
|
||||
fetch := func() (string, error) { calls++; return "result", nil }
|
||||
if got, _ := withCache("wc_hit", 60, fetch); got != "result" {
|
||||
t.Fatalf("首次应返回回源结果, got %q", got)
|
||||
}
|
||||
if got, _ := withCache("wc_hit", 60, fetch); got != "result" {
|
||||
t.Fatalf("命中应返回缓存结果, got %q", got)
|
||||
}
|
||||
if calls != 1 {
|
||||
t.Fatalf("命中缓存不应回源, fetch 调用 %d 次", calls)
|
||||
}
|
||||
|
||||
errCalls := 0
|
||||
errFetch := func() (string, error) { errCalls++; return "", fmt.Errorf("boom") }
|
||||
withCache("wc_miss", 60, errFetch)
|
||||
withCache("wc_miss", 60, errFetch)
|
||||
if errCalls != 2 {
|
||||
t.Fatalf("失败响应不应被缓存, fetch 调用 %d 次", errCalls)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user