Skip to content

fix(query-planner): restore missing defer dependencies after transitive reduction#9123

Open
duckki wants to merge 1 commit intodevfrom
duckki/rh-1172
Open

fix(query-planner): restore missing defer dependencies after transitive reduction#9123
duckki wants to merge 1 commit intodevfrom
duckki/rh-1172

Conversation

@duckki
Copy link
Copy Markdown
Contributor

@duckki duckki commented Apr 1, 2026

Background

When the query planner builds a fetch dependency graph for queries with @defer, it performs a transitive reduction to eliminate redundant edges. However, when a direct edge from an ancestor fetch to a deferred fetch node is also reachable transitively through an intermediate fetch, the reduction removes the direct edge. This causes extract_children_and_deferred_dependencies to miss registering the ancestor as a defer dependency, so at runtime the deferred node never receives the ancestor's broadcast data (__typename, entity keys, and other fields at that response path). The deferred fetch is then silently skipped, returning null for fields that should have data.

Proposal

The fix tracks defer-crossing edges that are removed during transitive reduction in a new reduced_defer_edges field on FetchDependencyGraph. After reduction, collect_reduced_defer_dependencies examines each removed edge: it navigates the source fetch's selection set down to the target's merge_at level using selection_set_at_path, then checks whether the source provides any fields the deferred target's inputs require (using SelectionMap::get() with SelectionKey for type-condition-aware matching). Only edges where a real field intersection exists are restored as dependencies, avoiding unnecessary over-registration.

Testing

The change includes two new federation-level snapshot tests—one for the original reproducer where the intermediate fetch has a deeper merge_at path, and one where the intermediate has the same merge_at as the deferred target—plus a router-level integration test that exercises the full defer execution pipeline and verifies the deferred response is not silently dropped.


Checklist

Complete the checklist (and note appropriate exceptions) before the PR is marked ready-for-review.

  • PR description explains the motivation for the change and relevant context for reviewing
  • PR description links appropriate GitHub/Jira tickets (creating when necessary)
  • Changeset is included for user-facing changes
  • Changes are compatible[^1]
  • Documentation[^2] completed
  • Performance impact assessed and acceptable
  • Metrics and logs are added[^3] and documented
  • Tests added and passing[^4]
    • Unit tests
    • Integration tests
    • Manual tests, as necessary

@duckki duckki requested review from a team as code owners April 1, 2026 22:10
@apollo-librarian
Copy link
Copy Markdown
Contributor

apollo-librarian bot commented Apr 1, 2026

✅ Docs preview has no changes

The preview was not built because there were no changes.

Build ID: 560c66488c0a0589718af1c4
Build Logs: View logs


✅ AI Style Review — No Changes Detected

No MDX files were changed in this pull request.

Review Log: View detailed log

This review is AI-generated. Please use common sense when accepting these suggestions, as they may not always be accurate or appropriate for your specific context.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

@duckki, please consider creating a changeset entry in /.changesets/. These instructions describe the process and tooling.

…ve reduction

When the fetch dependency graph's transitive reduction removes a direct
edge from an ancestor fetch to a deferred node (because a transitive
path exists through an intermediate fetch), the ancestor is not
registered as a defer dependency. At runtime, the deferred node never
receives the ancestor's data (__typename, entity keys), causing the
deferred fetch to be silently skipped.

Track defer-crossing edges removed during reduction and restore them as
dependencies when the ancestor's selection set has intersection
with the deferred target's required inputs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant