Skip to content

refactor(rpc): one dispatcher - #27486

Merged
OrcaWin merged 1 commit into
mainfrom
OrcaWin/p399-D1
Oct 11, 2026
Merged

OrcaWin merged 1 commit into
mainfrom
OrcaWin/p399-D1

Conversation

@OrcaWin

@OrcaWin OrcaWin commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 1 0 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1
Prod 6 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​157 $\color{#cf222e}{\Huge{\mathbf{−}}}$​257 $\color{#cf222e}{\Huge{\mathbf{−}}}$​100

ELI5

The code that answers RPC requests on an Orca host lived in five files, and the "run one ordinary request" logic was written twice: once for plain request/response connections and once for streaming connections. This PR puts it in one file with one copy of that logic. Nothing a user or a connected client sees changes.

What Changed

  • Before: RpcDispatcher (dispatcher.ts) delegated streaming calls to a second class, RpcStreamingDispatcher (rpc-streaming-dispatcher.ts). Both called a shared helper (dispatcher-unary-method-invocation.ts), and each repeated the same admission and success/error reply code around it. The helper also depended on two tiny files, each used in one place (dispatcher-caller-fingerprint.ts, dispatcher-client-browser-routing.ts).
  • After: RpcDispatcher has dispatch and dispatchStreaming that share one private admit (the existing admission prologue) and one private invokeUnary. The four files above are deleted. Their logic moved over unchanged, in the same order:
    • admission still runs exactly once per request, and the synchronous fast path is kept, so replies keep their order;
    • client-hosted browser routing, legacy orchestration handling, the rule that a legacy coordinator's fingerprint wins, local caller-fingerprint minting (still only computed when needed), and durable mutation execution are all unchanged;
    • only the request/response path runs the emulator probes, as before;
    • all errors still go through mapDispatcherError, so the git/filesystem error text and the PTY error prefix that the renderer matches are unchanged;
    • the cancellation signal still reaches handlers through the same transport context.
  • config/scripts/pr-code-change-scope.mjs no longer lists the deleted file. Its src/main/runtime/rpc/dispatcher prefix still covers dispatcher.ts, so the cross-version wire suites still run when the dispatcher changes.

Net lines: production −101 (+157 / −258 across src/ and the CI scope script), tests −1.

Why

With two copies of the unary path, every RPC change had to be made twice and could drift between the two transports. One class with one unary path removes that risk. Alternatives I considered:

  • Keep the helper file and only delete the streaming class. That saves fewer lines and still leaves dispatch spread across files that each have a single importer.
  • Also fold dispatcher-streaming-feature-emitter.ts and dispatcher-stream-options.ts, as the plan suggested. I kept both: a native-chat payload budget test imports the emitter directly, and the stream-options type is imported by seven modules.
  • Also drop the optional call to routeClientHostedBrowserRpc, as the plan suggested. I tried a required call: 640 tests in 94 dispatcher test files failed, because their fake runtimes don't define the method. The optional call stays, now as plain ?. with a one-line reason instead of a type cast.

Linked Issue

Part of the Phase 3.99 cleanup (PR D1). Maintainer PR, no separate issue.

Visual Proof

N/A. Internal refactor with no UI or behaviour change.

Testing

  • pnpm tc, pnpm lint, oxlint, pnpm run check:code-quality:changed: all pass.

  • pnpm run build:electron-vite, build:cli, build:orcad: all pass.

  • Dead-code proof: rg across src, config, scripts, tests, mobile, packages and dotfiles (including the @ts-nocheck files) finds no remaining reference to the deleted files or symbols.

  • Every test file that constructs RpcDispatcher (165 files, including the transport-parity, orchestration legacy compatibility and takeover, emulator/computer error and browser client automation suites), plus the native-chat payload budget test and the CI scope tests: 1519 passed, 2 failed. The same 2 also fail on unmodified main (structured-agent-session-subscriber-journal-retention, session-tabs-inventory-rpc publication-waiter abort).

  • Platforms: macOS locally. The change touches no OS-specific, SSH or path code.

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

No new tests: this is a behaviour-preserving move, and the existing transport-parity and dispatcher suites cover both transports.

Review

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

No wire or schema change. Replies, error codes and messages, and reply ordering are unchanged for owner, mobile and paired-runtime callers, so mixed client and host versions are unaffected. SSH and folder workspaces are unaffected.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@coderabbitai

coderabbitai Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a5a858f2-274f-4925-a191-6ab5fd9f74e8

📥 Commits

Reviewing files that changed from the base of the PR and between a56e335b6ef94896bd30631073d459d124f13a27 and 88baf48.


You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 62e20f0d-d2d6-4997-aa56-854c99199e42


📥 Commits

Reviewing files that changed from the base of the PR and between 741f953 and a56e335b6ef94896bd30631073d459d124f13a27.



📒 Files selected for processing (7)
  • config/scripts/pr-code-change-scope-cross-version-send-path.test.mjs
  • config/scripts/pr-code-change-scope.mjs
  • src/main/runtime/rpc/dispatcher-caller-fingerprint.ts
  • src/main/runtime/rpc/dispatcher-client-browser-routing.ts
  • src/main/runtime/rpc/dispatcher-unary-method-invocation.ts
  • src/main/runtime/rpc/dispatcher.ts
  • src/main/runtime/rpc/rpc-streaming-dispatcher.ts


💤 Files with no reviewable changes (6)
  • config/scripts/pr-code-change-scope.mjs
  • src/main/runtime/rpc/dispatcher-unary-method-invocation.ts
  • src/main/runtime/rpc/dispatcher-client-browser-routing.ts
  • src/main/runtime/rpc/dispatcher-caller-fingerprint.ts
  • config/scripts/pr-code-change-scope-cross-version-send-path.test.mjs
  • src/main/runtime/rpc/rpc-streaming-dispatcher.ts


Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.




📝 Walkthrough
📝 Walkthrough

Walkthrough

RpcDispatcher now owns shared request admission and unary and streaming execution. Its unary path retains browser routing and legacy orchestration handling, derives caller fingerprints, executes durable mutations, and records feature interactions. Its streaming path handles admitted unary methods and streaming handlers, then serializes results or mapped errors. The separate dispatch helper modules were removed. The cross-version wire detector and its test no longer include the streaming dispatcher path.



Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to a56e3

No merge-blocking behavior change was established; the refactor is mergeable after normal checks.

Pre-merge checks | Passed 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check Passed The title clearly identifies the main change: consolidating RPC dispatch into one dispatcher.
Description check Passed The description includes all required sections and clearly explains the change, rationale, testing results, compatibility impact, and review considerations. It documents the two known baseline test fa…
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.



✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR



  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

Fold the streaming dispatcher, the unary invocation helper and two
single-importer helpers into dispatcher.ts so request/response and
streaming-unary share one unary path. No behaviour change.
@OrcaWin
OrcaWin merged commit 3835a42 into main Oct 11, 2026
36 checks passed
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