2.8 KiB
Goal: Fix Source List Auto-Refresh After Adding New Source
Issue Reference
GitHub Issue: #526
Problem
When a user adds a new source to a notebook (via URL, file upload, or text), the source list in the notebook page does not auto-refresh. The user sees a toast notification saying "Source Queued" but must manually refresh the browser to see the new source appear in the list.
Root Cause
The notebook page uses useNotebookSources() which queries with key QUERY_KEYS.sourcesInfinite(notebookId) = ['sources', 'infinite', notebookId].
However, the mutation hooks that create sources only invalidate different query keys:
useCreateSourceinvalidatesQUERY_KEYS.sources(notebookId)=['sources', notebookId]useFileUploadinvalidatesQUERY_KEYS.sources(variables.notebookId)=['sources', notebookId]
React Query's prefix matching does NOT cascade from ['sources', notebookId] to ['sources', 'infinite', notebookId] because the second element differs (notebookId vs 'infinite').
Note: Other hooks like useDeleteSource, useUpdateSource, etc. correctly use queryClient.invalidateQueries({ queryKey: ['sources'] }) which IS a prefix of all source queries and does cascade properly.
Fix
Add sourcesInfinite query key invalidation in both useCreateSource and useFileUpload hooks in frontend/src/lib/hooks/use-sources.ts.
Key Files
frontend/src/lib/hooks/use-sources.ts- Contains all source mutation hooks (main fix location)frontend/src/lib/api/query-client.ts- DefinesQUERY_KEYSincludingsourcesInfinitefrontend/src/app/(dashboard)/notebooks/[id]/page.tsx- Notebook page that usesuseNotebookSourcesfrontend/src/app/(dashboard)/notebooks/components/SourcesColumn.tsx- Source list UI component
Implementation Details
In useCreateSource (line ~89-139):
After each QUERY_KEYS.sources(notebookId) invalidation, also invalidate QUERY_KEYS.sourcesInfinite(notebookId).
In useFileUpload (line ~195-220):
After QUERY_KEYS.sources(variables.notebookId) invalidation, also invalidate QUERY_KEYS.sourcesInfinite(variables.notebookId).
Why This Works
- The backend creates the source record immediately (even for async processing, with title "Processing...")
- The source is linked to the notebook immediately
- So invalidating the query will refetch and show the new source
SourceCardalready hasuseSourceStatus()that polls every 2 seconds during processing, so the status will auto-update
Gotchas
- No need for polling/delays - the source record exists in DB when the API returns
- No need for WebSocket/SSE - simple cache invalidation is sufficient
- The async path creates a minimal source with "Processing..." title that gets updated when processing completes
SourceCardalready handles status polling viauseSourceStatus()hook