Repository navigation
[Fusion] Keep duplicate lookup targets as result cursors - #10613
Merged
Merged
Conversation
When one lookup result is merged into a primary target and several additional targets, the primary target is completed from the source data and, when every completed value is a non-null, non-enum leaf of an object with the same selection set, the completed rows are copied into each additional target instead of completing the same source data again. Targets that do not qualify, merges with errors and pocketed errors keep the existing completion.
Additional targets of a lookup variable set are kept as cursors into the result document instead of building a path per target. The merge uses the cursors directly while no value that references an object or a list was replaced since the targets were collected, and resolves the target from the root by its path otherwise. The paths of a CompactPathSegment are created on first access, so error attribution, telemetry and custom clients keep working.
Contributor
Patch coverage98.3% of changed lines covered (230/234)
Uncovered changed lines (JSON){
"sha": "f40d685d69bfb8f5d1e24762356ebcace669ac57",
"files": [
{ "path": "src/HotChocolate/Fusion/src/Fusion.Execution/Text/Json/CompactPathSegment.cs", "ranges": [[85, 85], [90, 90]] },
{ "path": "src/HotChocolate/Fusion/src/Fusion.Execution/Execution/Results/FetchResultStore.cs", "ranges": [[951, 952]] }
]
}Project coverage: 59.2% (313424/529767 lines) |
This was referenced Oct 18, 2026
tobias-tengler
changed the base branch from
main
to
tte/fusion-copy-duplicate-lookup-leaf-values
October 19, 2026 06:44
Base automatically changed from
tte/fusion-copy-duplicate-lookup-leaf-values
to
main
October 21, 2026 03:56
michaelstaib
marked this pull request as ready for review
October 21, 2026 03:59
Resolves the duplicate lookup target copy from #10612 onto cursor targets: the leaf copy and entity reuse read additional targets through AdditionalTargets, and TryAssignLeafValue tracks structure replacements like the other value writers. Drops the row offset copy helpers that #10612 no longer uses.
- Creating the paths of target cursors now fails when their result document is no longer the store's result, instead of reading the rows of a released document. - The additional target accumulator is presized with the number of targets and rents its path buffer only when a path is added, so cursor-only accumulation no longer grows an unused buffer. - Tests cover merging after a structure change makes the cursors stale, the released document guard, and accumulators that mix paths and cursors.
michaelstaib
self-requested a review
October 21, 2026 04:26
- Paths created from target cursors on first access are allocated instead of rented from the request path pool, which never got them back and grew for every event of a subscription. - The benchmark copy passes the capacity hint like production. - Tests cover the cursor fast path for later variable sets, duplicate targets of a source result with errors, and accumulator growth with paths. - Documentation states the contracts of the accumulator, the cursor paths and the target resolver.
michaelstaib
approved these changes
Oct 21, 2026
This was referenced Oct 25, 2026
Merged
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.
When several lookup targets have the same requirement values, the gateway sends one variable set and merges its result into the primary target and every additional target. For the federation benchmark query this means 324 lookup targets but only 7 distinct variable sets, and each duplicate target re-runs path building, variable writing and the full merge, which resolves the target again by walking its path from the root.
This PR keeps the additional targets as cursors into the result document. The merge uses the cursors directly while no value that references an object or a list has been replaced since they were collected, and otherwise resolves the target from the root by its path as before. The paths of the additional targets are created on first access, so error attribution, telemetry and custom source schema clients keep working.
mainmainmainmainThe micro benchmark runs the whole federation benchmark query through the gateway executor against canned subgraph responses; this PR takes about a fifth off the request on both families. In the k6 screen (constant scenario, A B B A, 3 × 30 s runs per invocation, PR measured together with #10612) composite-schema gains 425 RPS and apollo-federation 330 RPS, about 6.5σ and 8σ of main's run-to-run noise (σ ≈ 65 and 40 RPS), while gateway CPU per request drops by 17% and 18% and p99 improves on both.