From b53a97b36d394222d44c38ee91ca0bb4367525d9 Mon Sep 17 00:00:00 2001 From: weichen Date: Fri, 18 Sep 2026 03:40:24 +0000 Subject: [PATCH] =?UTF-8?q?fix(ctxmgr):=20=E8=A1=A5=E9=BD=90=20rows.Err()?= =?UTF-8?q?=20=E6=A3=80=E6=9F=A5=EF=BC=88R-2=EF=BC=8Cctxmgr=20=E5=8C=85?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A 类硬失败返回;manager 降级读路径用 slog.Warn 保持既有容忍语义。 Co-authored-by: Cursor --- internal/ctxmgr/case_indexing.go | 2 +- internal/ctxmgr/chat_digest.go | 6 ++++++ internal/ctxmgr/chat_history.go | 4 ++-- internal/ctxmgr/chat_memory.go | 3 +++ internal/ctxmgr/chat_search.go | 7 +++++-- internal/ctxmgr/chat_unread.go | 4 ++++ internal/ctxmgr/chat_window.go | 8 +++++++- internal/ctxmgr/manager.go | 13 +++++++++++++ internal/ctxmgr/project_dialogue.go | 3 +++ internal/ctxmgr/recategorize.go | 3 +++ 10 files changed, 47 insertions(+), 6 deletions(-) diff --git a/internal/ctxmgr/case_indexing.go b/internal/ctxmgr/case_indexing.go index 6cf2a76f..7aa2142c 100644 --- a/internal/ctxmgr/case_indexing.go +++ b/internal/ctxmgr/case_indexing.go @@ -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() diff --git a/internal/ctxmgr/chat_digest.go b/internal/ctxmgr/chat_digest.go index 2a0adf1f..508ed506 100644 --- a/internal/ctxmgr/chat_digest.go +++ b/internal/ctxmgr/chat_digest.go @@ -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 } diff --git a/internal/ctxmgr/chat_history.go b/internal/ctxmgr/chat_history.go index 54a189e1..d61dd695 100644 --- a/internal/ctxmgr/chat_history.go +++ b/internal/ctxmgr/chat_history.go @@ -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() diff --git a/internal/ctxmgr/chat_memory.go b/internal/ctxmgr/chat_memory.go index 5b0ec34b..e75d70d8 100644 --- a/internal/ctxmgr/chat_memory.go +++ b/internal/ctxmgr/chat_memory.go @@ -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 diff --git a/internal/ctxmgr/chat_search.go b/internal/ctxmgr/chat_search.go index 88b84a36..375309d4 100644 --- a/internal/ctxmgr/chat_search.go +++ b/internal/ctxmgr/chat_search.go @@ -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) diff --git a/internal/ctxmgr/chat_unread.go b/internal/ctxmgr/chat_unread.go index d2a768de..b2d5499b 100644 --- a/internal/ctxmgr/chat_unread.go +++ b/internal/ctxmgr/chat_unread.go @@ -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() } diff --git a/internal/ctxmgr/chat_window.go b/internal/ctxmgr/chat_window.go index 22cf0420..e735bd55 100644 --- a/internal/ctxmgr/chat_window.go +++ b/internal/ctxmgr/chat_window.go @@ -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() diff --git a/internal/ctxmgr/manager.go b/internal/ctxmgr/manager.go index 80a80ba4..4e8d79b8 100644 --- a/internal/ctxmgr/manager.go +++ b/internal/ctxmgr/manager.go @@ -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() diff --git a/internal/ctxmgr/project_dialogue.go b/internal/ctxmgr/project_dialogue.go index 69a0467e..49d3b2d0 100644 --- a/internal/ctxmgr/project_dialogue.go +++ b/internal/ctxmgr/project_dialogue.go @@ -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 { diff --git a/internal/ctxmgr/recategorize.go b/internal/ctxmgr/recategorize.go index 98250818..2a8a4c8f 100644 --- a/internal/ctxmgr/recategorize.go +++ b/internal/ctxmgr/recategorize.go @@ -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 {