fix(ctxmgr): 补齐 rows.Err() 检查(R-2,ctxmgr 包)

A 类硬失败返回;manager 降级读路径用 slog.Warn 保持既有容忍语义。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
weichen
2026-09-18 03:40:24 +00:00
co-authored by Cursor
parent ba1fc71f16
commit b53a97b36d
10 changed files with 47 additions and 6 deletions
+1 -1
View File
@@ -196,7 +196,7 @@ func (m *ContextManager) SearchSimilarCases(ctx context.Context, opts CaseSearch
results = append(results, item)
}
}
return results, nil
return results, rows.Err()
}
m.mu.RLock()
+6
View File
@@ -50,6 +50,9 @@ func (m *ContextManager) GenerateDailyDigest(ctx context.Context, sessionID, day
rec.CreatedAt = createdAt
msgs = append(msgs, rec)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan digest messages failed: %w", err)
}
} else {
m.mu.RLock()
for _, r := range m.messages[sessionID] {
@@ -367,6 +370,9 @@ func (m *ContextManager) ListDailyDigests(ctx context.Context, sessionID, from,
_ = json.Unmarshal(oqBytes, &d.OpenQuestions)
digests = append(digests, d)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan digests failed: %w", err)
}
return digests, nil
}
+2 -2
View File
@@ -152,7 +152,7 @@ func (m *ContextManager) ListChatSessions(ctx context.Context, filter SessionFil
sessions = append(sessions, item)
}
}
return sessions, nil
return sessions, rows.Err()
}
m.mu.RLock()
@@ -224,7 +224,7 @@ func (m *ContextManager) GetChatHistory(ctx context.Context, sessionID string, l
msgs = append(msgs, rec)
}
}
return msgs, nil
return msgs, rows.Err()
}
m.mu.RLock()
+3
View File
@@ -285,6 +285,9 @@ func (m *ContextManager) SearchChatMemory(ctx context.Context, opts ChatMemorySe
}
}
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan memory chunks failed: %w", err)
}
sort.Slice(candidates, func(i, j int) bool {
return candidates[i].FinalScore > candidates[j].FinalScore
+5 -2
View File
@@ -101,7 +101,7 @@ func (m *ContextManager) searchChatMessagesKeywordDB(ctx context.Context, q Chat
MatchedBy: "keyword",
})
}
return hits, nil
return hits, rows.Err()
}
// searchChatMessagesFuzzyDB 模糊相似度检索 (Postgres pg_trgm similarity)
@@ -160,7 +160,7 @@ func (m *ContextManager) searchChatMessagesFuzzyDB(ctx context.Context, q ChatSe
MatchedBy: "fuzzy",
})
}
return hits, nil
return hits, rows.Err()
}
// searchChatMessagesSemanticDB 语义向量检索 (通过 context_memory_chunks 或降级为 keyword)
@@ -232,6 +232,9 @@ func (m *ContextManager) searchChatMessagesSemanticDB(ctx context.Context, q Cha
MatchedBy: "semantic",
})
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan semantic search hits failed: %w", err)
}
if len(hits) == 0 {
return m.searchChatMessagesKeywordDB(ctx, q)
+4
View File
@@ -322,6 +322,10 @@ func (m *ContextManager) markChatReadPG(ctx context.Context, req MarkChatReadReq
futureIDs = append(futureIDs, mid)
}
}
if err := rows.Err(); err != nil {
rows.Close()
return nil, fmt.Errorf("scan future unread ids failed: %w", err)
}
rows.Close()
}
+7 -1
View File
@@ -72,6 +72,9 @@ func (m *ContextManager) getChatWindowPG(ctx context.Context, q ChatWindowQuery)
descDays = append(descDays, d.Format("2006-01-02"))
}
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan chat window days failed: %w", err)
}
if len(descDays) == 0 {
return &ChatWindowResult{
@@ -601,6 +604,9 @@ func (m *ContextManager) ListChatDates(ctx context.Context, sessionID string) ([
st.Categories[cat] += cnt
}
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan chat dates failed: %w", err)
}
res := make([]ChatDateStat, 0, len(orderedKeys))
for _, k := range orderedKeys {
@@ -688,7 +694,7 @@ func (m *ContextManager) ListChatCategories(ctx context.Context, sessionID strin
LastMessageID: maxID,
})
}
return res, nil
return res, rows.Err()
}
m.mu.RLock()
+13
View File
@@ -1,6 +1,7 @@
package ctxmgr
import (
"log/slog"
"context"
"encoding/json"
"errors"
@@ -383,6 +384,9 @@ func (m *ContextManager) GetUserContext(ctx context.Context, projectID, userID i
userCtx.RecentChats = append(userCtx.RecentChats, r)
}
}
if err := rows.Err(); err != nil {
slog.Warn("ctxmgr_recent_chats_scan_incomplete", "error", err)
}
}
} else {
m.mu.RLock()
@@ -410,6 +414,9 @@ func (m *ContextManager) GetUserContext(ctx context.Context, projectID, userID i
rawActs = append(rawActs, it)
}
}
if err := rows.Err(); err != nil {
slog.Warn("ctxmgr_user_activities_scan_incomplete", "error", err)
}
}
} else {
m.mu.RLock()
@@ -481,6 +488,9 @@ func (m *ContextManager) GetProjectContext(ctx context.Context, projectID int64)
}
}
}
if err := rows.Err(); err != nil {
slog.Warn("ctxmgr_project_activities_scan_incomplete", "error", err)
}
pCtx.AllActivities = ApplyTimeDecayToActivities(rawActs, m.decayCfg)
}
} else {
@@ -727,6 +737,9 @@ func (m *ContextManager) ReflectUserPreference(ctx context.Context, userID int64
msgs = append(msgs, r)
}
}
if err := rows.Err(); err != nil {
slog.Warn("ctxmgr_reflect_msgs_scan_incomplete", "error", err)
}
}
} else {
m.mu.RLock()
+3
View File
@@ -69,6 +69,9 @@ func (m *ContextManager) CollectProjectDialogue(ctx context.Context, projectID i
}
msgs = append(msgs, rec)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan project dialogue failed: %w", err)
}
} else {
m.mu.RLock()
for sessionID, sessionMsgs := range m.messages {
+3
View File
@@ -64,6 +64,9 @@ func (m *ContextManager) RecategorizeMessages(ctx context.Context, sessionID str
}
msgs = append(msgs, r)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("scan messages for recategorize failed: %w", err)
}
var lastUserMsg *recatMsg
for _, msg := range msgs {