mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
fix(chats): archive chat tree with single query instead of loop (#22496)
## Problem When archiving an agent with subagents, the children briefly flash in the sidebar as root-level items before disappearing. Two issues: 1. **Backend:** Archive used N+1 queries — a recursive DFS (`archiveChatTree`, no transaction) or BFS loop (`chatd.ArchiveChat`, N+1 queries in a tx) to walk the tree and archive each chat individually. 2. **Frontend:** The SSE `deleted` event handler only filtered out the parent chat from the cache. Children remained briefly, got promoted to root-level by `buildChatTree`, then disappeared on the next re-fetch. ## Fix **Backend:** Replace both tree-walk implementations with a single SQL query: ```sql UPDATE chats SET archived = true, updated_at = NOW() WHERE id = @id OR root_chat_id = @id; ``` This leverages the existing `root_chat_id` column (already indexed) to archive the entire tree atomically. **Frontend:** When a `deleted` event arrives, also filter out any chats whose `root_chat_id` matches the deleted chat, so children vanish from the sidebar immediately with the parent. ## Changes - `coderd/database/queries/chats.sql` — Added `ArchiveChatTreeByID` query - `coderd/chats.go` — Use single query, delete `archiveChatTree` function - `coderd/chatd/chatd.go` — Simplify `ArchiveChat` to use single query - `coderd/database/dbauthz/dbauthz.go` — Auth wrapper for new query - `coderd/chats_test.go` — Added `TestArchiveChat/ArchivesChildren` subtest - `site/src/pages/AgentsPage/AgentsPage.tsx` — Filter children in SSE handler - Generated files updated via `make gen`
This commit is contained in:
@@ -2876,7 +2876,8 @@ func (q *sqlQuerier) AcquireChat(ctx context.Context, arg AcquireChatParams) (Ch
|
||||
}
|
||||
|
||||
const archiveChatByID = `-- name: ArchiveChatByID :exec
|
||||
UPDATE chats SET archived = true, updated_at = NOW() WHERE id = $1::uuid
|
||||
UPDATE chats SET archived = true, updated_at = NOW()
|
||||
WHERE id = $1 OR root_chat_id = $1
|
||||
`
|
||||
|
||||
func (q *sqlQuerier) ArchiveChatByID(ctx context.Context, id uuid.UUID) error {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
-- name: ArchiveChatByID :exec
|
||||
UPDATE chats SET archived = true, updated_at = NOW() WHERE id = @id::uuid;
|
||||
UPDATE chats SET archived = true, updated_at = NOW()
|
||||
WHERE id = @id OR root_chat_id = @id;
|
||||
|
||||
-- name: UnarchiveChatByID :exec
|
||||
UPDATE chats SET archived = false, updated_at = NOW() WHERE id = @id::uuid;
|
||||
|
||||
Reference in New Issue
Block a user