Batch consecutive same-RPC recipes via BatchVisit RPC#6983
Merged
jkschneider merged 8 commits intomainfrom Mar 15, 2026
Merged
Conversation
When a composite recipe has consecutive RPC-based recipes (e.g., all C#), skip the host-side getObject() call between them, letting the remote keep the modified tree in localObjects. The tree is fetched once at the end of the batch, saving 2N-2 GetObject round-trips per source file for N consecutive same-RPC recipes. Key changes: - Add `deleted` field to VisitResponse across all languages - Add SearchResult recipe attribution via recipeName RPC field - Add deferral logic to RewriteRpc (deferGetObject, fetchDeferredResult) - Add batch detection and flush logic to RecipeRunCycle - Add nextRecipe lookahead to RecipeStack - Update C#/Python/JS Visit handlers to check localObjects first - Add integration tests for deferral scenarios
Instead of deferring GetObject calls between individual Visit RPCs for consecutive same-RPC recipes (which required 6 mutable fields, recipeName on SearchResult in 3 languages, and RpcReceiveQueue interception), use a single BatchVisit RPC that runs N visitors in sequence on the remote and returns per-visitor metadata (modified, deleted, newSearchResultIds). The host accumulates BatchVisitItem entries and sends one BatchVisit at the batch boundary. For edits, one getObject fetches the final tree. For scans, no getObject is needed. SearchResult attribution comes from diffing marker IDs before/after each visitor on the remote side.
Collect SearchResult IDs once before the loop and maintain a running set, avoiding redundant full-tree walks on each iteration.
Port the Java visitor's prefix and marker visitation to C#: - Add VisitSpace, VisitMarkers, and VisitMarker virtual methods to JavaVisitor<P> - Wire VisitSpace and VisitMarkers into all visit methods in JavaVisitor and CSharpVisitor - Revert SearchResultCollector to use VisitMarker override (no longer needs Accept workaround)
Remove externs/attributeLists visiting from CompilationUnit and NamespaceDeclaration (those fields don't exist on main yet). Keep prefix/markers visiting for all methods.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When a composite recipe has consecutive sub-recipes that all run on the same RPC peer, the scheduler now batches them into a single
BatchVisitRPC call instead of sending individualVisit+GetObjectround-trips for each one.BatchVisitRPC method runs N visitors in sequence on the remote and returns per-visitor metadata (modified, deleted, searchResultIds)BatchVisitItementries for consecutive same-RPC recipes and sends oneBatchVisitat the batch boundaryGetObjectfetches the final tree state at the end of the batchGetObjectneeded (scan results are discarded)For N consecutive same-RPC recipes, this reduces N Visit RPCs + N GetObject RPCs down to 1 BatchVisit RPC + 1 GetObject RPC.
Changes
New files:
BatchVisit.java— request class withBatchVisitItem, plusHandlerthat runs visitors in sequence and diffs SearchResult marker IDsBatchVisitResponse.java— per-visitor result withmodified,deleted,hasNewMessages,searchResultIdsbatch-visit.ts— TypeScript BatchVisit handlerCore changes:
RewriteRpc.java—batchVisit()method, register"BatchVisit"handlerRpcRecipe.java—@Getteronrpc,editVisitor,scanVisitorfields (needed to build batch items without triggering individual Visit RPCs)RecipeRunCycle.java—BatchStatefor edit and scan phases;flushBatch()sends one BatchVisit + one GetObject and builds per-recipe attribution from response;flushScanBatch()for scan phaseRecipeStack.java—nextRecipelookahead (used for batch boundary detection)Remote handlers (~50 lines each):
server.py—handle_batch_visit()+_collect_search_result_ids()RewriteRpcServer.cs—[JsonRpcMethod("BatchVisit")]handler +CollectSearchResultIds()Test plan
consecutiveSameRpcRecipesAreBatchedAndProduceCorrectResult— two consecutive same-RPC recipesthreeConsecutiveSameRpcRecipes— three consecutive same-RPC recipessameRpcBatchFollowedByNonRpcRecipe— batch flush at RPC/non-RPC boundarysingleRpcRecipeNoBatch— single RPC recipe uses normal Visit pathrewrite-coretest suite passes