Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fragment variable definitions erased in subgraph queries #3119

Merged
merged 7 commits into from
Aug 22, 2024

Conversation

clenfest
Copy link
Contributor

Fixes #3112

Before creating an Operation, we call collectUsedVariables, which will only pull values from the selection set and not from fragments. This isn't great, because a variable used in a fragment won't be collected, and it doesn't make sense to collect variables from fragments because it's before they are optimized and many will be unused.

The inelegant solution I came up with is to pass in available variables in calls to optimize or generateQueryFragments for an operation where we can add back in the unused variables. This should be ok, because we are guaranteed that exactly one of them will get called by toPlanNode. Pretty sure there won't be too much overhead added because we'll only call this once per subgraph fetch.

Fixes #3112

Before creating an Operation, we call `collectUsedVariables`, which will only pull values from the selection set and not from fragments. This isn't great, because a variable used in a fragment won't be collected, and it doesn't make sense to collect variables from fragments because it's before they are optimized and many will be unused.

The inelegant solution I came up with is to pass in available variables in calls to `optimize` or  `generateQueryFragments` for an operation where we can add back in the unused variables. This should be ok, because we are guaranteed that exactly one of them will get called by `toPlanNode`. Pretty sure there won't be too much overhead added because we'll only call this once per subgraph fetch.
@clenfest clenfest requested a review from a team as a code owner August 15, 2024 14:27
Copy link

changeset-bot bot commented Aug 15, 2024

🦋 Changeset detected

Latest commit: c99cfcc

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 7 packages
Name Type
@apollo/query-planner Patch
@apollo/federation-internals Patch
@apollo/gateway Patch
@apollo/composition Patch
@apollo/query-graphs Patch
@apollo/subgraph Patch
apollo-federation-integration-testsuite Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link

netlify bot commented Aug 15, 2024

Deploy Preview for apollo-federation-docs canceled.

Name Link
🔨 Latest commit 6d0a5d0
🔍 Latest deploy log https://app.netlify.com/sites/apollo-federation-docs/deploys/66be106b5d821b0008d7ce88

Copy link

codesandbox-ci bot commented Aug 15, 2024

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@clenfest clenfest marked this pull request as draft August 15, 2024 17:17
@duckki
Copy link
Contributor

duckki commented Aug 15, 2024

Rust QP went a different way by not using fragments with unexpected variables in them, instead of including added variables in the query (@goto-bus-stop). I hope Rust QP and JS QP go the same direction at least for now.

See this commit: apollographql/router@8c8340d

@goto-bus-stop
Copy link
Member

goto-bus-stop commented Aug 16, 2024

Yeah. I didn't realise this was the same case. Optimizing can introduce a new variable reference, but only inside a dead branch (otherwise, the variable reference would already be in the expanded selection set). So there's three correct ways to go:

  1. Removing dead branches when reusing a fragment
  2. Ignoring fragments that introduce new variable dependencies
  3. Counting variable references after optimizing

My preference was 2), because 1) is hard and 3) is adding a "dead" variable to the subgraph query. That said, a fix is a fix, and this is not common enough that it will be a big problem for mismatch testing with Rust, I think.

@clenfest clenfest changed the base branch from main to next August 21, 2024 17:00
@clenfest clenfest marked this pull request as ready for review August 21, 2024 17:02
internals-js/src/operations.ts Outdated Show resolved Hide resolved
internals-js/src/operations.ts Outdated Show resolved Hide resolved
internals-js/src/operations.ts Outdated Show resolved Hide resolved
@duckki
Copy link
Contributor

duckki commented Aug 21, 2024

I don't have a strong opinion on which way we want to fix this in JS. I don't want to hold you back especially since this case is not common.

Copy link
Contributor

@sachindshinde sachindshinde left a comment

Choose a reason for hiding this comment

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

I've tweaked the logic to keep variable definition ordering the same and avoid some copies, but otherwise LGTM.

@sachindshinde sachindshinde merged commit e0a5075 into next Aug 22, 2024
12 of 13 checks passed
@sachindshinde sachindshinde deleted the clenfest/fix_variables_for_fragments branch August 22, 2024 02:57
sachindshinde pushed a commit that referenced this pull request Aug 22, 2024
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to
version-2.9.0-beta, this PR will be updated.

⚠️⚠️⚠️⚠️⚠️⚠️

`version-2.9.0-beta` is currently in **pre mode** so this branch has
prereleases rather than normal releases. If you want to exit
prereleases, run `changeset pre exit` on `version-2.9.0-beta`.

⚠️⚠️⚠️⚠️⚠️⚠️

# Releases
## @apollo/composition@2.9.0-beta.0

### Minor Changes

- Implements two new directives for defining custom costs for demand
control. The `@cost` directive allows setting a custom weight to a
particular field in the graph, overriding the default cost calculation.
The `@listSize` directive gives the cost calculator information about
how to estimate the size of lists returned by subgraphs. This can either
be a static size or a value derived from input arguments, such as paging
parameters.
([#3074](#3074))

### Patch Changes

- Reduce memory overhead during satisfiability checking when there are
many options.
([#3109](#3109))

- Updated dependencies
\[[`acfe3193429c7f99b4fc564b20828aaa8659a75c`](acfe319),
[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/query-graphs@2.9.0-beta.0
    -   @apollo/federation-internals@2.9.0-beta.0

## @apollo/federation-internals@2.9.0-beta.0

### Minor Changes

- Implements two new directives for defining custom costs for demand
control. The `@cost` directive allows setting a custom weight to a
particular field in the graph, overriding the default cost calculation.
The `@listSize` directive gives the cost calculator information about
how to estimate the size of lists returned by subgraphs. This can either
be a static size or a value derived from input arguments, such as paging
parameters.
([#3074](#3074))

### Patch Changes

- Reduce memory overhead during satisfiability checking when there are
many options.
([#3109](#3109))

- Fix issue where variable was not passed into subgraph when embedded in
a fragment
([#3119](#3119))

## @apollo/gateway@2.9.0-beta.0

### Patch Changes

- Avoid type explosion for inline fragments where the type condition is
an interface that implements the parent type.
([#3122](#3122))

- Reduce memory overhead during satisfiability checking when there are
many options.
([#3109](#3109))

- Updated dependencies
\[[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/federation-internals@2.9.0-beta.0
    -   @apollo/composition@2.9.0-beta.0
    -   @apollo/query-planner@2.9.0-beta.0

## @apollo/query-graphs@2.9.0-beta.0

### Patch Changes

- Avoid type explosion for inline fragments where the type condition is
an interface that implements the parent type.
([#3122](#3122))

- Updated dependencies
\[[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/federation-internals@2.9.0-beta.0

## @apollo/query-planner@2.9.0-beta.0

### Patch Changes

- Fix issue where variable was not passed into subgraph when embedded in
a fragment
([#3119](#3119))

- Updated dependencies
\[[`acfe3193429c7f99b4fc564b20828aaa8659a75c`](acfe319),
[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/query-graphs@2.9.0-beta.0
    -   @apollo/federation-internals@2.9.0-beta.0

## @apollo/subgraph@2.9.0-beta.0

### Patch Changes

- Updated dependencies
\[[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/federation-internals@2.9.0-beta.0

## apollo-federation-integration-testsuite@2.9.0-beta.0

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
tninesling pushed a commit that referenced this pull request Aug 27, 2024
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @apollo/composition@2.9.0

### Minor Changes

- Implements two new directives for defining custom costs for demand
control. The `@cost` directive allows setting a custom weight to a
particular field in the graph, overriding the default cost calculation.
The `@listSize` directive gives the cost calculator information about
how to estimate the size of lists returned by subgraphs. This can either
be a static size or a value derived from input arguments, such as paging
parameters.
([#3074](#3074))

### Patch Changes

- Reduce memory overhead during satisfiability checking when there are
many options.
([#3109](#3109))

- Updated dependencies
\[[`acfe3193429c7f99b4fc564b20828aaa8659a75c`](acfe319),
[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/query-graphs@2.9.0
    -   @apollo/federation-internals@2.9.0

## @apollo/federation-internals@2.9.0

### Minor Changes

- Implements two new directives for defining custom costs for demand
control. The `@cost` directive allows setting a custom weight to a
particular field in the graph, overriding the default cost calculation.
The `@listSize` directive gives the cost calculator information about
how to estimate the size of lists returned by subgraphs. This can either
be a static size or a value derived from input arguments, such as paging
parameters.
([#3074](#3074))

### Patch Changes

- Reduce memory overhead during satisfiability checking when there are
many options.
([#3109](#3109))

- Fix issue where variable was not passed into subgraph when embedded in
a fragment
([#3119](#3119))

## @apollo/gateway@2.9.0

### Patch Changes

- Avoid type explosion for inline fragments where the type condition is
an interface that implements the parent type.
([#3122](#3122))

- Reduce memory overhead during satisfiability checking when there are
many options.
([#3109](#3109))

- Updated dependencies
\[[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/federation-internals@2.9.0
    -   @apollo/composition@2.9.0
    -   @apollo/query-planner@2.9.0

## @apollo/query-graphs@2.9.0

### Patch Changes

- Avoid type explosion for inline fragments where the type condition is
an interface that implements the parent type.
([#3122](#3122))

- Updated dependencies
\[[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/federation-internals@2.9.0

## @apollo/query-planner@2.9.0

### Patch Changes

- Fix issue where variable was not passed into subgraph when embedded in
a fragment
([#3119](#3119))

- Updated dependencies
\[[`acfe3193429c7f99b4fc564b20828aaa8659a75c`](acfe319),
[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/query-graphs@2.9.0
    -   @apollo/federation-internals@2.9.0

## @apollo/subgraph@2.9.0

### Patch Changes

- Updated dependencies
\[[`02c2a34a62c3717a4885449172e404f19ebf66c9`](02c2a34),
[`0ccfd937d4b4a576f890665ceebbd7986fac5d0c`](0ccfd93),
[`e0a5075c0d12a0e2f7ef303b246e3216a139d3e0`](e0a5075)]:
    -   @apollo/federation-internals@2.9.0

## apollo-federation-integration-testsuite@2.9.0

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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.

Undefined variable reference in generated subgraph query
4 participants