feat(platform): add threadMetadata shadow table for efficient thread queries#509
Conversation
…queries Replace direct agent component thread queries with a local threadMetadata shadow table indexed by userId/chatType/status. This eliminates the need to paginate and filter through all agent threads client-side, enabling efficient single-index lookups for listing, latest-thread, and filtering. - Add threadMetadata table schema with composite indexes - Update create/delete/update thread helpers to maintain shadow records - Rewrite listThreads to query shadow table with pagination - Rewrite getLatestThreadWithMessageCount to use shadow table index - Add backfill migration for existing threads - Add list_threads tests and error boundary in chat layout
Greptile SummaryThis PR implements a shadow table pattern to optimize thread queries. The Key Changes:
Issues Found:
Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| services/platform/convex/threads/schema.ts | defines threadMetadata shadow table with appropriate indexes for efficient queries by threadId and composite (userId, chatType, status, createdAt) |
| services/platform/convex/migrations/backfill_thread_metadata.ts | idempotent migration that backfills shadow records from agent component, correctly handles pagination and chatType extraction from summary JSON |
| services/platform/convex/threads/create_chat_thread.ts | creates thread in agent component and shadow table synchronously; has timestamp mismatch issue between Date.now() and agent _creationTime |
| services/platform/convex/threads/update_chat_thread.ts | updates title in both agent component and shadow table; correctly handles missing shadow records with optional update |
| services/platform/convex/threads/delete_chat_thread.ts | archives thread in both tables and schedules sub-thread cleanup; handles missing shadow records gracefully |
| services/platform/convex/threads/list_threads.ts | replaced multi-page agent component iteration with single indexed shadow table query, dramatically improving performance for thread listing |
Sequence Diagram
sequenceDiagram
participant Client
participant listThreads
participant threadMetadata
participant AgentComponent
Note over Client,AgentComponent: Before: Multi-page agent query
Client->>listThreads: Get threads (old)
loop Up to 5 pages
listThreads->>AgentComponent: Query page
AgentComponent-->>listThreads: Raw threads
listThreads->>listThreads: Filter by status & chatType
end
listThreads-->>Client: Filtered threads
Note over Client,AgentComponent: After: Single shadow table query
Client->>listThreads: Get threads (new)
listThreads->>threadMetadata: Query with index
threadMetadata-->>listThreads: Pre-filtered threads
listThreads-->>Client: Threads (much faster)
Note over Client,AgentComponent: CRUD keeps tables in sync
Client->>AgentComponent: Create/Update/Delete thread
AgentComponent-->>Client: Success
Client->>threadMetadata: Mirror operation
threadMetadata-->>Client: Success
Last reviewed commit: 997b591
📝 WalkthroughWalkthroughThis PR introduces a new thread metadata storage layer and refactors thread management to use it. Changes include: creating a new Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@services/platform/convex/threads/delete_chat_thread.test.ts`:
- Around line 74-88: The test currently sets dbQueryChain.first to always
resolve to null so the code path that calls ctx.db.patch for threadMetadata
archival is never hit; update or add a test where dbQueryChain.first (or
mockRunQuery for threadMetadata) resolves to a mock metadata record (e.g., { id:
'meta123', archived: false, ... }) and then assert that mockPatch (ctx.db.patch)
is called with the expected selector and patch payload to mark the
threadMetadata archived; locate the mocks defined (mockPatch,
dbQueryChain.first, mockDb, ctx) and modify the setup for that test to return
the metadata and include an assertion on mockPatch being invoked with correct
arguments.
Summary
threadMetadatashadow table to eliminate expensive multi-page agent component queries when listing/filtering threadsmigrations/backfill_thread_metadata) to populate shadow records for existing threadsChatHistorySidebarin an error boundary for resilienceChanges
threadMetadatatable with indexes onthreadIdand composite(userId, chatType, status, createdAt)list_threads.ts: Replaced multi-page agent component iteration with a single indexed query on the shadow tableget_latest_thread_with_message_count.ts: Uses shadow table index instead of agent component querycreate_chat_thread.ts: Inserts shadow record on thread creationupdate_chat_thread.ts: Patches shadow record on title updatedelete_chat_thread.ts: Archives shadow record on thread deletionlistThreadsandisGeneralThreadTest plan
npx vitest runfor unit tests🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
Stability
Performance
Improvements