fix(desktop): v2 file tree no longer waits on git.getStatus in shared tRPC batch#3400
Conversation
… tRPC batch The workspace tRPC client used httpBatchLink, which returns a batched response only when every procedure in the batch resolves. On workspace switch, FilesTab's filesystem.listDirectory (ms) was batched with WorkspaceSidebar's git.getStatus (5-10s on a large monorepo), so the file tree stalled behind git for every switch. Swap to httpBatchStreamLink so responses stream as each procedure completes, allow the trpc-accept header through CORS on the host service, and drop a now-unnecessary staleTime:0 override on listDirectory.fetch.
|
Caution Review failedPull request was closed or merged during review No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe PR modifies tRPC client-server configuration and request handling across three files: updating the workspace client's transport layer to use streaming, expanding CORS header allowances for Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 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 docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 Preview Deployment🔗 Preview Links
Preview updates automatically with new commits |
Greptile SummaryThis PR fixes a performance bottleneck in the v2 desktop workspace file tree by swapping Key changes:
Confidence Score: 4/5Safe to merge after addressing the staleTime regression in useFileTree; the core streaming fix and CORS change are correct. Two of three changes are clean and correct. The one concrete bug — apps/desktop/src/renderer/hooks/host-service/useFileTree/useFileTree.ts — staleTime removal breaks forced refreshes triggered by filesystem events within the 5-second cache window. Important Files Changed
Sequence DiagramsequenceDiagram
participant FilesTab
participant WorkspaceSidebar
participant BatchStreamLink as httpBatchStreamLink
participant HostService
Note over FilesTab,HostService: Before (httpBatchLink) — file tree stalls behind git
FilesTab->>BatchStreamLink: listDirectory (fast ~ms)
WorkspaceSidebar->>BatchStreamLink: git.getStatus (slow 5-10s)
BatchStreamLink->>HostService: Batched request
Note over HostService: Both run in parallel on server
HostService-->>BatchStreamLink: Response only after ALL complete (~10s)
BatchStreamLink-->>FilesTab: listDirectory result (delayed ~10s)
BatchStreamLink-->>WorkspaceSidebar: git.getStatus result
Note over FilesTab,HostService: After (httpBatchStreamLink) — file tree renders immediately
FilesTab->>BatchStreamLink: listDirectory (fast ~ms)
WorkspaceSidebar->>BatchStreamLink: git.getStatus (slow 5-10s)
BatchStreamLink->>HostService: Batched request (trpc-accept header negotiates stream)
Note over HostService: Both run in parallel on server
HostService-->>BatchStreamLink: listDirectory streams back (~ms)
BatchStreamLink-->>FilesTab: listDirectory result (immediate)
HostService-->>BatchStreamLink: git.getStatus streams back (~10s)
BatchStreamLink-->>WorkspaceSidebar: git.getStatus result
Reviews (1): Last reviewed commit: "fix(desktop): v2 file tree no longer wai..." | Re-trigger Greptile |
| const result = await utils.filesystem.listDirectory.fetch({ | ||
| workspaceId, | ||
| absolutePath, | ||
| }); |
There was a problem hiding this comment.
fs:events refreshes silenced by 5-second stale window
Removing staleTime: 0 here introduces a real regression for the filesystem-event path. React Query's fetchQuery (what .fetch() delegates to) will return the in-cache response without going to the network whenever the data was fetched within the last STALE_TIME_MS (5 s). This conflicts with the fs:events handler, which calls loadDirectory(parentPath, true) as an explicit signal that on-disk state has changed and needs a fresh read.
Typical scenario:
- User switches workspace →
listDirectoryresolves in a few ms, result cached. - User creates/deletes a file in the same terminal window (well within 5 s).
fs:eventsfires →loadDirectory(parentPath, true)called..fetch()returns the 5-seconds-stale cache entry — the new/deleted file is invisible.
The force flag already bypasses the internal loadedDirectories guard; it should also bypass the React Query cache. The minimal fix is to forward staleTime: 0 when force is true:
| const result = await utils.filesystem.listDirectory.fetch({ | |
| workspaceId, | |
| absolutePath, | |
| }); | |
| const result = await utils.filesystem.listDirectory.fetch( | |
| { workspaceId, absolutePath }, | |
| force ? { staleTime: 0 } : undefined, | |
| ); |
This keeps the 5-second cache for ordinary expand/collapse (fast path) while ensuring any forced refresh — whether from an fs:events event or an explicit refreshPath call — always hits the network.
… tRPC batch (superset-sh#3400) The workspace tRPC client used httpBatchLink, which returns a batched response only when every procedure in the batch resolves. On workspace switch, FilesTab's filesystem.listDirectory (ms) was batched with WorkspaceSidebar's git.getStatus (5-10s on a large monorepo), so the file tree stalled behind git for every switch. Swap to httpBatchStreamLink so responses stream as each procedure completes, allow the trpc-accept header through CORS on the host service, and drop a now-unnecessary staleTime:0 override on listDirectory.fetch.
Summary
httpBatchLink, which returns a batched response only after every procedure in the batch resolves. On v2 workspace switch,FilesTab'sfilesystem.listDirectory(a few ms offs.readdir) was batched withWorkspaceSidebar'sgit.getStatus(5–10s on a large monorepo: runsgit.status(),ls-files --others --ignored,buildBranch×2,getChangedFilesForDiff, andgit diff --numstat --cachedin parallel). Result: the file tree stalled behind git for every workspace switch even though its own work was done in ms.httpBatchLink→httpBatchStreamLinkinWorkspaceClientProvider. Same batching, but responses stream as each procedure completes, so fast calls return immediately and slow calls stream later on the same connection. No per-procedure routing needed.trpc-acceptheader through the host-service CORS config (httpBatchStreamLinksends it to negotiate streamed responses; the existingallowHeaderslist was rejecting it at preflight).staleTime: 0override onlistDirectory.fetchinuseFileTreeso React Query's default 5s stale window can serve rapid re-fetches from cache.Explains all observations: v1 is unaffected (IPC, no HTTP batching), the Changes tab was fast because it re-used the already-cached git status, and the delay hit every switch because each new
workspaceIdwarms a fresh git status.Test plan
bun devdesktop, open a large monorepo workspace/trpcgit.getStatusis still streamingfs:eventsinvalidation still refreshes the file tree after on-disk changesbun run typecheck✅bun run lint✅Summary by cubic
Make the v2 file tree render immediately on workspace switch by streaming tRPC batch responses. Fixes long delays in large monorepos where
git.getStatuswas blockingfilesystem.listDirectory.httpBatchLink→httpBatchStreamLinkinWorkspaceClientProvider(@trpc/client) so each procedure streams back independently.trpc-acceptin host-service CORS to enable streamed responses.staleTime: 0override onfilesystem.listDirectory.fetchto use the default cache window.Written for commit 4898520. Summary will update on new commits.
Summary by CodeRabbit
Release Notes
trpc-acceptheaders, improving request compatibility.