Skip to content

migrate old file streaming to new modern interface (w/ flow control)#3096

Open
sawka wants to merge 7 commits intomainfrom
sawka/remove-old-filestream
Open

migrate old file streaming to new modern interface (w/ flow control)#3096
sawka wants to merge 7 commits intomainfrom
sawka/remove-old-filestream

Conversation

@sawka
Copy link
Member

@sawka sawka commented Mar 20, 2026

No description provided.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 20, 2026

Walkthrough

This PR refactors the file streaming architecture by transitioning from channel-based RPC streaming commands to a stream-broker approach. Key changes include introducing RpcClientRouteId as a global variable to track authenticated client route identifiers; removing legacy FileReadStreamCommand and RemoteStreamFileCommand implementations across backend, client, and server layers; updating streamReadFromFile to use explicit stream broker lifecycle management instead of fsutil.ReadFileStreamToWriter; removing pre-read file size validation from file operations; updating frontend directory listing to use FileListStreamCommand instead of single reads; removing associated mock filesystem and RPC method implementations; and updating RPC type interfaces to reflect the architectural change.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive No pull request description was provided by the author, but given the PR has objectives and a clear, specific title that indicates the migration work, the absence of a description makes evaluation inconclusive. Add a description explaining the motivation for the migration, any breaking changes, and testing approach to help reviewers understand the full context of this refactoring.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'migrate old file streaming to new modern interface (w/ flow control)' accurately describes the main objective of the changeset, which involves replacing legacy streaming RPC methods with modern flow-controlled alternatives throughout the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch sawka/remove-old-filestream

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link

Deploying waveterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: 09b4f7c
Status: ✅  Deploy successful!
Preview URL: https://5cd491ac.waveterm.pages.dev
Branch Preview URL: https://sawka-remove-old-filestream.waveterm.pages.dev

View logs

@kilo-code-bot
Copy link
Contributor

kilo-code-bot bot commented Mar 20, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Overview

The PR migrates from the old file streaming interface to a new modern interface with flow control. The changes are well-structured:

  • Removes deprecated streaming commands (FileReadStreamCommand, RemoteStreamFileCommand)
  • Adds proper route ID tracking (RpcClientRouteId) for stream routing
  • Updates both Go backend and TypeScript frontend to use the new FileListStreamCommand
  • Properly initializes stream broker with route IDs in all entry points

Key Changes Verified

Area Status
Route ID initialization ✅ Properly set in all call sites
Null checks ✅ Added for StreamBroker and RpcClientRouteId
Type consistency ✅ CommandFileStreamData and CommandRemoteFileStreamData have StreamMeta field
Frontend migration ✅ Uses FileListStreamCommand correctly with finfo from component scope
Files Reviewed (18 files)
  • cmd/server/main-server.go
  • cmd/wsh/cmd/wshcmd-connserver.go
  • cmd/wsh/cmd/wshcmd-file-util.go
  • cmd/wsh/cmd/wshcmd-file.go
  • cmd/wsh/cmd/wshcmd-root.go
  • frontend/app/store/wshclientapi.ts
  • frontend/app/view/preview/preview-directory.tsx
  • frontend/app/view/preview/previewenv.ts
  • frontend/preview/mock/mockfilesystem.ts
  • frontend/preview/mock/mockwaveenv.test.ts
  • frontend/preview/mock/mockwaveenv.ts
  • frontend/types/gotypes.d.ts
  • pkg/remote/fileshare/fsutil/fsutil.go
  • pkg/remote/fileshare/wshfs/wshfs.go
  • pkg/wshrpc/wshclient/wshclient.go
  • pkg/wshrpc/wshremote/wshremote_file.go
  • pkg/wshrpc/wshrpctypes_file.go
  • pkg/wshrpc/wshserver/wshserver.go

Reviewed by minimax-m2.5-20260211 · 1,193,623 tokens

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmd/wsh/cmd/wshcmd-connserver.go (1)

186-199: ⚠️ Potential issue | 🔴 Critical

Return bareRouteId instead of routeId from setupConnServerRpcClientWithRouter.

The function creates two route IDs with distinct purposes:

  • bareRouteId (line 193): Random proc route for the bare client making RPC requests
  • routeId (line 187): Connection route for the connserver receiving requests

Line 199 returns routeId, but the callers at lines 239 and 364 assign the return value to bareRouteId and pass it as RpcClientRouteId for stream reader operations. This variable is then used as readerRouteId in CreateStreamReader() calls (wshremote_file.go:174), where it represents the route of the client making the request. The reader route should be the bare client's route, not the connection route.

Fix
-	return connServerClient, routeId, nil
+	return connServerClient, bareRouteId, nil
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/wsh/cmd/wshcmd-connserver.go` around lines 186 - 199, In
setupConnServerRpcClientWithRouter, the function currently returns routeId but
callers expect the bare client's route; change the returned route value to
bareRouteId so callers receive the bare client's route ID. Update the return
statement in setupConnServerRpcClientWithRouter to return bareRouteId (the
identifier created as bareRouteId and used to register bareClient) instead of
routeId, ensuring callers that assign the second return to
bareRouteId/readerRouteId get the correct client route for CreateStreamReader
and related operations.
🧹 Nitpick comments (1)
frontend/app/view/preview/preview-directory.tsx (1)

589-617: Clean migration to streaming directory listing.

The implementation correctly:

  • Uses FileListStreamCommand with async iteration
  • Safely handles optional chunk?.fileinfo
  • Properly conditionally adds ".." based on finfo.dir !== finfo.path (per the FileInfo type where Dir equals Path for root directories)
  • Adds helpful error logging

One consideration: the async generator stream isn't explicitly cancelled if the component unmounts mid-stream. In practice, this is often acceptable since the stream will naturally complete or error, but for very long directory listings you might want to use an AbortController pattern or check a mounted flag.

♻️ Optional: Add cancellation support for large directories
     useEffect(
         () =>
             fireAndForget(async () => {
                 const entries: FileInfo[] = [];
+                let cancelled = false;
                 try {
                     const remotePath = await model.formatRemoteUri(dirPath, globalStore.get);
                     const stream = env.rpc.FileListStreamCommand(TabRpcClient, { path: remotePath }, null);
                     for await (const chunk of stream) {
+                        if (cancelled) break;
                         if (chunk?.fileinfo) {
                             entries.push(...chunk.fileinfo);
                         }
                     }
                     // ... rest of logic
                 } catch (e) {
+                    if (cancelled) return;
                     console.error("Directory Read Error", e);
                     // ...
                 }
+                if (cancelled) return;
                 setUnfilteredData(entries);
-            }),
+            }),
+            return () => { cancelled = true; };
         [conn, dirPath, refreshVersion]
     );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/view/preview/preview-directory.tsx` around lines 589 - 617, The
directory streaming loop using FileListStreamCommand can continue after the
component unmounts; add cancellation so we don't call
setUnfilteredData/setErrorMsg on an unmounted component: create an
AbortController (or a `let cancelled = false` flag) inside the effect that calls
model.formatRemoteUri and env.rpc.FileListStreamCommand, pass the abort signal
to the RPC if supported or break the for-await loop when aborted, and in the
effect cleanup abort the controller (or set cancelled = true); ensure before
pushing entries or calling setUnfilteredData/setErrorMsg you check the
abort/cancelled flag. Use the existing symbols FileListStreamCommand, stream,
setUnfilteredData, setErrorMsg, model.formatRemoteUri and the enclosing
useEffect to locate where to add the controller/flag and cleanup.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@cmd/wsh/cmd/wshcmd-connserver.go`:
- Around line 186-199: In setupConnServerRpcClientWithRouter, the function
currently returns routeId but callers expect the bare client's route; change the
returned route value to bareRouteId so callers receive the bare client's route
ID. Update the return statement in setupConnServerRpcClientWithRouter to return
bareRouteId (the identifier created as bareRouteId and used to register
bareClient) instead of routeId, ensuring callers that assign the second return
to bareRouteId/readerRouteId get the correct client route for CreateStreamReader
and related operations.

---

Nitpick comments:
In `@frontend/app/view/preview/preview-directory.tsx`:
- Around line 589-617: The directory streaming loop using FileListStreamCommand
can continue after the component unmounts; add cancellation so we don't call
setUnfilteredData/setErrorMsg on an unmounted component: create an
AbortController (or a `let cancelled = false` flag) inside the effect that calls
model.formatRemoteUri and env.rpc.FileListStreamCommand, pass the abort signal
to the RPC if supported or break the for-await loop when aborted, and in the
effect cleanup abort the controller (or set cancelled = true); ensure before
pushing entries or calling setUnfilteredData/setErrorMsg you check the
abort/cancelled flag. Use the existing symbols FileListStreamCommand, stream,
setUnfilteredData, setErrorMsg, model.formatRemoteUri and the enclosing
useEffect to locate where to add the controller/flag and cleanup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9e43edeb-c402-4904-9967-37870a07f6af

📥 Commits

Reviewing files that changed from the base of the PR and between a6062c2 and 68dce2f.

📒 Files selected for processing (18)
  • cmd/server/main-server.go
  • cmd/wsh/cmd/wshcmd-connserver.go
  • cmd/wsh/cmd/wshcmd-file-util.go
  • cmd/wsh/cmd/wshcmd-file.go
  • cmd/wsh/cmd/wshcmd-root.go
  • frontend/app/store/wshclientapi.ts
  • frontend/app/view/preview/preview-directory.tsx
  • frontend/app/view/preview/previewenv.ts
  • frontend/preview/mock/mockfilesystem.ts
  • frontend/preview/mock/mockwaveenv.test.ts
  • frontend/preview/mock/mockwaveenv.ts
  • frontend/types/gotypes.d.ts
  • pkg/remote/fileshare/fsutil/fsutil.go
  • pkg/remote/fileshare/wshfs/wshfs.go
  • pkg/wshrpc/wshclient/wshclient.go
  • pkg/wshrpc/wshremote/wshremote_file.go
  • pkg/wshrpc/wshrpctypes_file.go
  • pkg/wshrpc/wshserver/wshserver.go
💤 Files with no reviewable changes (7)
  • frontend/types/gotypes.d.ts
  • cmd/wsh/cmd/wshcmd-file.go
  • pkg/wshrpc/wshserver/wshserver.go
  • pkg/wshrpc/wshrpctypes_file.go
  • pkg/wshrpc/wshclient/wshclient.go
  • frontend/app/store/wshclientapi.ts
  • pkg/remote/fileshare/fsutil/fsutil.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant