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

Implement @cost and @listSize directives for demand control #3074

Merged
merged 14 commits into from
Jul 22, 2024

Conversation

tninesling
Copy link
Contributor

Overview

Implements two new directives for demand control, based on the IBM Cost Specification.

directive @cost(weight: Int!) on 
  | ARGUMENT_DEFINITION
  | ENUM
  | FIELD_DEFINITION
  | INPUT_FIELD_DEFINITION
  | OBJECT
  | SCALAR

directive @listSize(
  assumedSize: Int,
  slicingArguments: [String!],
  sizedFields: [String!],
  requireOneSlicingArgument: Boolean = true
) on FIELD_DEFINITION

The @cost directive allows users to specify a custom weight for fields, enums, input objects, and arguments. The weight is used in the demand control cost calculation, both for static estimates as well as actual cost calculations.

The @listSize directive allows users to specify expected sizes of list fields in their schema. This can be a static value set through assumedSize or a dynamic value using slicingArguments to get the value from some paging parameters.

Differences from the spec

The main difference from the IBM spec is that we use an Int! for weight argument of @cost. This allows the parser to enforce this is parameterized with proper numeric values instead of finding out at runtime that an invalid String! weight was passed.

Caveats for shared fields

When @cost or @listSize are used on a @shareable field with different values, the composed directive will use a merged value that takes the maximum weight or assumed size, when applicable.

@tninesling tninesling requested a review from a team as a code owner July 10, 2024 20:04
Copy link

changeset-bot bot commented Jul 10, 2024

🦋 Changeset detected

Latest commit: 36d6c71

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

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

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

codesandbox-ci bot commented Jul 10, 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.

# Overview

This PR targets the branch of an existing open PR. The main difference
is that this one combines the new `@cost` and `@listSize` directives are
combined into the same spec. This required a small update to how the
supergraph schema is prepared.

When a directive spec definition is imported by a subgraph, it was
previously included in the supergraph without an import argument. So a
subgraph with `@link(url: "https://specs.apollo.dev/cost/v0.1", import:
["@cost"])`, is translated to the supergraph as `@link(url:
"https://specs.apollo.dev/cost/v0.1")`. If multiple imports are
included, the supergraph wouldn't get any of them. With this change, the
supergraph now gets an equivalent `@link(url:
"https://specs.apollo.dev/cost/v0.1", import: ["@cost"])`.

## Renaming

The core/link directive can have an argument called "as" to rename the
directive from a spec. This would take a subgraph import `@link(url:
"https://specs.apollo.dev/cost/v0.1", import: [{ name: "@cost", as:
"@renamedCost" }])`, and translate it to `@link(url:
"https://specs.apollo.dev/cost/v0.1", as: "renamedCost")`. With this
change, the supergraph now gets an equivalent `@link(url:
"https://specs.apollo.dev/cost/v0.1", import: [{ name: "@cost", as:
"@renamedCost" }])`.

## Import aggregation

As we add directive spec features to the supergraph, we check for
existing links with the same feature version (both the link identity and
the version must match). If one is found, we append the new directive to
the existing list of imports.
@tninesling tninesling requested a review from clenfest July 17, 2024 17:46
@tninesling tninesling merged commit 0ccfd93 into next Jul 22, 2024
15 checks passed
@tninesling tninesling deleted the tninesling/demand-control-directives-without-join branch July 22, 2024 17:45
tninesling added a commit that referenced this pull request Aug 14, 2024
As a follow-up to #3074,
properly support specifying `@cost` on `SCALAR` and `OBJECT` locations.
tninesling added a commit that referenced this pull request Aug 14, 2024
<!-- ROUTER-457 -->

This pull request documents the directives added in
#3074. These will be
released in the next federation version (v2.9), which is targeted for
the end of the month.

Both directives are inspired by the [IBM cost
specification](https://ibm.github.io/graphql-specs/cost-spec.html#sec-The-Cost-Directive).
So, most of the documentation parrots their specification.

---------

Co-authored-by: Edward Huang <edward.huang@apollographql.com>
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.

2 participants