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

Add generate_query_fragments configuration option #4885

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changesets/config_generate_query_fragments.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### Add `generate_query_fragments` configuration option ([PR #4885](https://github.com/apollographql/router/pull/4885))

Add a new `supergraph` configuration option `generate_query_fragments`. When set to `true`, the query planner will extract inline fragments into fragment definitions before sending queries to subgraphs. This can significantly reduce the size of the query sent to subgraphs, but may increase the time it takes to plan the query. Note that this option and `reuse_query_fragments` are mutually exclusive; if both are set to `true`, `generate_query_fragments` will take precedence.

An example router configuration:

```yaml title="router.yaml"
supergraph:
generate_query_fragments: true
```

By [@trevor-scheer](https://github.com/trevor-scheer) in https://github.com/apollographql/router/pull/4885
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5735,9 +5735,9 @@ dependencies = [

[[package]]
name = "router-bridge"
version = "0.5.16+v2.7.1"
version = "0.5.17+v2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224f69e11bdc5c16b582f82cd18647e305d31c9c20110635fcdf790c46405777"
checksum = "2f183e217179b38a4283e76ca62e3149ebe96512e9b1bd6b3933abab863f9a2c"
dependencies = [
"anyhow",
"async-channel 1.9.0",
Expand Down
2 changes: 1 addition & 1 deletion apollo-router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ reqwest = { version = "0.11.24", default-features = false, features = [
"stream",
] }
# note: this dependency should _always_ be pinned, prefix the version with an `=`
router-bridge = "=0.5.16+v2.7.1"
router-bridge = "=0.5.17+v2.7.2"
rust-embed = "8.2.0"
rustls = "0.21.10"
rustls-native-certs = "0.6.3"
Expand Down
22 changes: 22 additions & 0 deletions apollo-router/src/configuration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,11 @@ pub(crate) struct Supergraph {
#[serde(rename = "experimental_reuse_query_fragments")]
pub(crate) reuse_query_fragments: Option<bool>,

/// Enable QP generation of fragments for subgraph requests
/// Default: false
#[serde(rename = "generate_query_fragments")]
trevor-scheer marked this conversation as resolved.
Show resolved Hide resolved
pub(crate) generate_query_fragments: Option<bool>,
BrynCooke marked this conversation as resolved.
Show resolved Hide resolved

/// Set to false to disable defer support
pub(crate) defer_support: bool,

Expand Down Expand Up @@ -641,16 +646,31 @@ impl Supergraph {
defer_support: Option<bool>,
query_planning: Option<QueryPlanning>,
reuse_query_fragments: Option<bool>,
generate_query_fragments: Option<bool>,
early_cancel: Option<bool>,
experimental_log_on_broken_pipe: Option<bool>,
) -> Self {
// reuse and generate query fragments are mutually exclusive options. If both
// are set and true, generate will be used and a warning will be
// emitted.
let reuse_query_fragments = if generate_query_fragments.is_some_and(|v| v) {
if reuse_query_fragments.is_some_and(|v| v) {
// warn the user that both are enabled and it's overridden
tracing::warn!("Both 'generate_query_fragments' and 'experimental_reuse_query_fragments' are explicitly enabled, 'experimental_reuse_query_fragments' will be overridden to false");
}
Some(false)
} else {
reuse_query_fragments
};

Self {
listen: listen.unwrap_or_else(default_graphql_listen),
path: path.unwrap_or_else(default_graphql_path),
introspection: introspection.unwrap_or_else(default_graphql_introspection),
defer_support: defer_support.unwrap_or_else(default_defer_support),
query_planning: query_planning.unwrap_or_default(),
reuse_query_fragments,
generate_query_fragments,
early_cancel: early_cancel.unwrap_or_default(),
experimental_log_on_broken_pipe: experimental_log_on_broken_pipe.unwrap_or_default(),
}
Expand All @@ -668,6 +688,7 @@ impl Supergraph {
defer_support: Option<bool>,
query_planning: Option<QueryPlanning>,
reuse_query_fragments: Option<bool>,
generate_query_fragments: Option<bool>,
early_cancel: Option<bool>,
experimental_log_on_broken_pipe: Option<bool>,
) -> Self {
Expand All @@ -678,6 +699,7 @@ impl Supergraph {
defer_support: defer_support.unwrap_or_else(default_defer_support),
query_planning: query_planning.unwrap_or_default(),
reuse_query_fragments,
generate_query_fragments,
early_cancel: early_cancel.unwrap_or_default(),
experimental_log_on_broken_pipe: experimental_log_on_broken_pipe.unwrap_or_default(),
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
source: apollo-router/src/configuration/tests.rs
assertion_line: 31
expression: "&schema"
---
{
Expand Down Expand Up @@ -2619,6 +2620,7 @@ expression: "&schema"
"path": "/",
"introspection": false,
"experimental_reuse_query_fragments": null,
"generate_query_fragments": null,
"defer_support": true,
"query_planning": {
"cache": {
Expand Down Expand Up @@ -2657,6 +2659,12 @@ expression: "&schema"
"type": "boolean",
"nullable": true
},
"generate_query_fragments": {
"description": "Enable QP generation of fragments for subgraph requests Default: false",
"default": null,
"type": "boolean",
"nullable": true
},
"introspection": {
"description": "Enable introspection Default: false",
"default": false,
Expand Down
16 changes: 16 additions & 0 deletions apollo-router/src/configuration/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,3 +1000,19 @@ fn find_struct_name(lines: &[&str], line_number: usize) -> Option<String> {
})
.next()
}

#[test]
fn it_prevents_reuse_and_generate_query_fragments_simultaneously() {
let conf = Configuration::builder()
.supergraph(
Supergraph::builder()
.generate_query_fragments(true)
.reuse_query_fragments(true)
.build(),
)
.build()
.unwrap();

assert_eq!(conf.supergraph.generate_query_fragments, Some(true));
assert_eq!(conf.supergraph.reuse_query_fragments, Some(false));
}
1 change: 1 addition & 0 deletions apollo-router/src/introspection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ mod introspection_tests {
}),
graphql_validation: true,
reuse_query_fragments: Some(false),
generate_query_fragments: None,
debug: None,
},
)
Expand Down
2 changes: 2 additions & 0 deletions apollo-router/src/query_planner/bridge_query_planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ impl BridgeQueryPlanner {
sdl,
QueryPlannerConfig {
reuse_query_fragments: configuration.supergraph.reuse_query_fragments,
generate_query_fragments: configuration.supergraph.generate_query_fragments,
incremental_delivery: Some(IncrementalDeliverySupport {
enable_defer: Some(configuration.supergraph.defer_support),
}),
Expand Down Expand Up @@ -287,6 +288,7 @@ impl BridgeQueryPlanner {
GraphQLValidationMode::Legacy | GraphQLValidationMode::Both
),
reuse_query_fragments: configuration.supergraph.reuse_query_fragments,
generate_query_fragments: configuration.supergraph.generate_query_fragments,
debug: Some(QueryPlannerDebugConfig {
bypass_planner_for_single_subgraph: None,
max_evaluated_plans: configuration
Expand Down
16 changes: 16 additions & 0 deletions docs/source/configuration/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,22 @@ example:
password: "${env.MY_PASSWORD}" #highlight-line
```

### Fragment reuse and generation

By default, the Apollo Router will attempt to reuse fragments from the original query while forming subgraph requests. This behavior can be disabled by setting the option to `false`:

```yaml
supergraph:
experimental_reuse_query_fragments: false
```

Alternatively, the Apollo Router can be configured to _generate_ fragments for subgraph requests. When set to `true`, the Apollo Router will extract _inline fragments only_ into fragment definitions before sending queries to subgraphs. This can significantly reduce the size of the query sent to subgraphs, but may increase the time it takes for planning. Note that this option and `experimental_reuse_query_fragments` are mutually exclusive; if both are explicitly set to `true`, `generate_query_fragments` will take precedence.

```yaml
supergraph:
generate_query_fragments: true
```

### Reusing configuration

You can reuse parts of your configuration file in multiple places using standard YAML aliasing syntax:
Expand Down
Loading