From b7439d7efb8810c0fb3fb61953a8ae686b5b768c Mon Sep 17 00:00:00 2001 From: Andrew Carlson <5479270+andrewicarlson@users.noreply.github.com> Date: Wed, 13 Nov 2024 11:03:13 -0600 Subject: [PATCH 1/8] Added 2 mermaid diagrams to demonstrate entity caching and entity cache invalidation --- .../routing/performance/caching/entity.mdx | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) diff --git a/docs/source/routing/performance/caching/entity.mdx b/docs/source/routing/performance/caching/entity.mdx index 218e6bd12a..d251c19e7e 100644 --- a/docs/source/routing/performance/caching/entity.mdx +++ b/docs/source/routing/performance/caching/entity.mdx @@ -61,6 +61,86 @@ With entity caching enabled for this example, the router can: - Cache the cart per user, with a small amount of data. - Cache inventory data with a short TTL or not cache it at all. +```mermaid +--- +title: Entity Caching using the "Price" entity +--- +flowchart RL + subgraph QueryResponse["JSON Response"] + n1["{ +   "products": [ +     { +       "name": "DraftSnowboard", +       "pastPurchases": ..., +       "price": { +         "amount": "1500", +         "currency_code": "USD" +       }, +       "quantity": "250" +     }, +     ... +   ] + }"] + end + + + + subgraph Subgraphs["Subgraphs"] + Purchases["Purchases"] + Inventory["Inventory"] + Price["Price"] + end + + subgraph PriceQueryFragment["Price Query Fragment (e.g. TTL 2200)"] + n2["{ +   "price": { +     "id": 101, +     "product_id": 12, +     "amount": 1500, +     "currency_code": "USD" +   } + }"] + end + + subgraph PurchaseHistoryQueryFragment["Purchase History Query Fragment"] + n3["{ +   "purchases": { +     "product_id": 12, +     "user_id": 2932, +     ... +   } + }"] + end + + subgraph InventoryQueryFragment["Inventory Query Fragment"] + n4["{ +   "inventory": { +     "id": 19, +     "product_id": 12, +     "quantity": 250 +   } + }"] + end + + Router + Database[("   ")] + + Router --> QueryResponse + Purchases --> Router + Inventory --> Router + Price --- Router + PriceQueryFragment --> Database + PurchaseHistoryQueryFragment --> Purchases + InventoryQueryFragment --> Inventory + Database --> Router + + style n1 text-align:left + style n2 text-align:left + style n3 text-align:left + style n4 text-align:left + style Price border:none,stroke-width:1px,stroke-dasharray:5 5,stroke:#A6A6A6 +``` + ## Use entity caching Follow this guide to enable and configure entity caching in the GraphOS Router. @@ -135,6 +215,54 @@ This entry contains an object with the `all` field to affect all subgraph reques ### Entity cache invalidation +```mermaid +%%{init: {"flowchart": {"htmlLabels": false}} }%% +flowchart RL + subgraph QueryResponse["Cache invalidation POST"] + n1["{ +   "kind": "subgraph", +   "subgraph": "price", +   "type": "Price", +   "key": { +     "id": "101" +   } + }"] + end + + subgraph Subgraphs["Subgraphs"] + Purchases["Purchases"] + Inventory["Inventory"] + Price["Price"] + end + + subgraph PriceQueryFragment["Price Query Fragment (e.g. TTL 2200)"] + n2["` ̶{̶ +   " ̶p̶r̶i̶c̶e̶": ̶{̶ +     " ̶i̶d̶": ̶1̶0̶1̶, +     " ̶p̶r̶o̶d̶u̶c̶t̶_̶i̶d̶": ̶1̶2̶, +     " ̶a̶m̶o̶u̶n̶t̶": ̶1̶5̶0̶0̶, +     "̶c̶u̶r̶r̶e̶n̶c̶y̶_̶c̶o̶d̶e̶": " ̶U̶S̶D̶" +    ̶}̶ + ̶}̶`"] + end + + Router + Database[("   ")] + + Router --> QueryResponse + Purchases --> Router + Inventory --> Router + Price --- Router + PriceQueryFragment --> Database + Database --> Router + + style n1 text-align:left + style Price border:none,stroke-width:1px,stroke-dasharray:5 5,stroke:#A6A6A6 + style Purchases border:none,stroke-width:1px,stroke-dasharray:5 5,stroke:#A6A6A6 + style Inventory border:none,stroke-width:1px,stroke-dasharray:5 5,stroke:#A6A6A6 + style n2 text-align:left +``` + When existing cache entries need to be replaced, the router supports a couple of ways for you to invalidate entity cache entries: - [**Invalidation endpoint**](#invalidation-http-endpoint) - the router exposes an invalidation endpoint that can receive invalidation requests from any authorized service. This is primarily intended as an alternative to the extensions mechanism described below. For example a subgraph could use it to trigger invalidation events "out of band" from any requests received by the router or a platform operator could use it to invalidate cache entries in response to events which aren't directly related to a router. - **Subgraph response extensions** - you can send invalidation requests via subgraph response extensions, allowing a subgraph to invalidate cached data right after a mutation. From ec54fb3c3bf9eca9e5c3500e0482559db8cf5d95 Mon Sep 17 00:00:00 2001 From: Iryna Shestak Date: Wed, 13 Nov 2024 19:18:23 +0100 Subject: [PATCH 2/8] Enable `generate_query_fragments` by default (#6013) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Renée --- ...ble_generate_query_fragments_by_default.md | 26 +++ .../src/query_plan/query_planner.rs | 25 ++- .../build_query_plan_tests/named_fragments.rs | 14 ++ .../named_fragments_preservation.rs | 21 ++- apollo-router-benchmarks/src/shared.rs | 2 +- ...factory__tests__defer_is_not_buffered.snap | 2 +- apollo-router/src/axum_factory/tests.rs | 2 +- apollo-router/src/configuration/mod.rs | 10 +- ...nfiguration__tests__schema_generation.snap | 4 +- apollo-router/src/plugin/test/mock/canned.rs | 2 +- .../src/plugins/authorization/tests.rs | 2 +- apollo-router/src/plugins/cache/tests.rs | 6 +- .../src/plugins/expose_query_plan.rs | 12 ++ .../src/plugins/include_subgraph_errors.rs | 28 +-- .../src/plugins/traffic_shaping/mod.rs | 3 + apollo-router/src/query_planner/tests.rs | 40 ++++- ...sts__escaped_quotes_in_string_literal.snap | 2 +- .../src/services/supergraph/tests.rs | 159 ++++++++++++++++-- .../fixtures/type_conditions/artwork.json | 4 +- .../type_conditions/artwork_disabled.json | 4 +- .../fixtures/type_conditions/search.json | 2 +- .../type_conditions/search_list_of_list.json | 4 +- .../search_list_of_list_of_list.json | 4 +- ..._config_update_query_fragments.router.yaml | 4 +- apollo-router/tests/integration/redis.rs | 26 ++- .../tests/samples/core/defer/plan.json | 4 +- .../enterprise/entity-cache/defer/plan.json | 4 +- .../invalidation-entity-key/plan.json | 8 +- apollo-router/tests/set_context.rs | 4 + ...ons___test_type_conditions_disabled-2.snap | 10 +- ...tions___test_type_conditions_disabled.snap | 10 +- ...ions___test_type_conditions_enabled-2.snap | 14 +- ...itions___test_type_conditions_enabled.snap | 14 +- ...ype_conditions_enabled_list_of_list-2.snap | 14 +- ..._type_conditions_enabled_list_of_list.snap | 14 +- ...itions_enabled_list_of_list_of_list-2.snap | 14 +- ...nditions_enabled_list_of_list_of_list.snap | 14 +- apollo-router/tests/tracing_common/mod.rs | 10 +- apollo-router/tests/type_conditions.rs | 7 +- .../source/reference/router/configuration.mdx | 25 ++- 40 files changed, 423 insertions(+), 151 deletions(-) create mode 100644 .changesets/feat_lrlna_enable_generate_query_fragments_by_default.md diff --git a/.changesets/feat_lrlna_enable_generate_query_fragments_by_default.md b/.changesets/feat_lrlna_enable_generate_query_fragments_by_default.md new file mode 100644 index 0000000000..2ae65008fd --- /dev/null +++ b/.changesets/feat_lrlna_enable_generate_query_fragments_by_default.md @@ -0,0 +1,26 @@ +### Compress subgraph operations by generating fragments + +The router now compresses operations sent to subgraphs by default by generating fragment +definitions and using them in the operation. + +Initially, the router is using a very simple transformation that is implemented in both +the JavaScript and Native query planners. We will improve the algorithm after the JavaScript +planner is no longer supported. + +This replaces a previous experimental algorithm that was enabled by default. +`experimental_reuse_query_fragments` attempted to intelligently reuse the fragment definitions +from the original operation. Fragment generation is much faster, and in most cases produces +better outputs too. + +If you are relying on the shape of fragments in your subgraph operations or tests, you can opt +out of the new algorithm with the configuration below. Note we strongly recommend against +relying on the shape of planned operations as new router features and optimizations may affect +it, and we intend to remove `experimental_reuse_query_fragments` in a future release. + +```yaml +supergraph: + generate_query_fragments: false + experimental_reuse_query_fragments: true +``` + +By [@lrlna](https://github.com/lrlna) in https://github.com/apollographql/router/pull/6013 diff --git a/apollo-federation/src/query_plan/query_planner.rs b/apollo-federation/src/query_plan/query_planner.rs index 1a3f1002f1..f6f4062760 100644 --- a/apollo-federation/src/query_plan/query_planner.rs +++ b/apollo-federation/src/query_plan/query_planner.rs @@ -63,7 +63,7 @@ pub struct QueryPlannerConfig { /// queries with many fragments. This option may be removed in the future in favour of /// [`generate_query_fragments`][QueryPlannerConfig::generate_query_fragments]. /// - /// Defaults to true. + /// Defaults to false. pub reuse_query_fragments: bool, /// If enabled, the query planner will extract inline fragments into fragment @@ -103,15 +103,16 @@ pub struct QueryPlannerConfig { pub type_conditioned_fetching: bool, } +#[allow(clippy::derivable_impls)] // it's derivable right now, but we might change the defaults impl Default for QueryPlannerConfig { fn default() -> Self { Self { - reuse_query_fragments: true, + reuse_query_fragments: false, generate_query_fragments: false, subgraph_graphql_validation: false, incremental_delivery: Default::default(), debug: Default::default(), - type_conditioned_fetching: Default::default(), + type_conditioned_fetching: false, } } } @@ -1381,7 +1382,11 @@ type User ) .unwrap(); - let planner = QueryPlanner::new(&supergraph, Default::default()).unwrap(); + let config = QueryPlannerConfig { + reuse_query_fragments: true, + ..Default::default() + }; + let planner = QueryPlanner::new(&supergraph, config).unwrap(); let plan = planner .build_query_plan(&document, None, Default::default()) .unwrap(); @@ -1442,7 +1447,11 @@ type User ) .unwrap(); - let planner = QueryPlanner::new(&supergraph, Default::default()).unwrap(); + let config = QueryPlannerConfig { + reuse_query_fragments: true, + ..Default::default() + }; + let planner = QueryPlanner::new(&supergraph, config).unwrap(); let plan = planner .build_query_plan(&document, None, Default::default()) .unwrap(); @@ -1504,7 +1513,11 @@ type User ) .unwrap(); - let planner = QueryPlanner::new(&supergraph, Default::default()).unwrap(); + let config = QueryPlannerConfig { + reuse_query_fragments: true, + ..Default::default() + }; + let planner = QueryPlanner::new(&supergraph, config).unwrap(); let plan = planner .build_query_plan(&document, None, Default::default()) .unwrap(); diff --git a/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments.rs b/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments.rs index a2d8b785f7..959069588c 100644 --- a/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments.rs +++ b/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments.rs @@ -1,6 +1,16 @@ +use apollo_federation::query_plan::query_planner::QueryPlannerConfig; + +fn reuse_fragments_config() -> QueryPlannerConfig { + QueryPlannerConfig { + reuse_query_fragments: true, + ..Default::default() + } +} + #[test] fn handles_mix_of_fragments_indirection_and_unions() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { parent: Parent @@ -74,6 +84,7 @@ fn another_mix_of_fragments_indirection_and_unions() { // This tests that the issue reported on https://github.com/apollographql/router/issues/3172 is resolved. let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { owner: Owner! @@ -252,6 +263,7 @@ fn another_mix_of_fragments_indirection_and_unions() { #[test] fn handles_fragments_with_interface_field_subtyping() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t1: T1! @@ -313,6 +325,7 @@ fn handles_fragments_with_interface_field_subtyping() { #[test] fn can_reuse_fragments_in_subgraph_where_they_only_partially_apply_in_root_fetch() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t1: T @@ -416,6 +429,7 @@ fn can_reuse_fragments_in_subgraph_where_they_only_partially_apply_in_root_fetch #[test] fn can_reuse_fragments_in_subgraph_where_they_only_partially_apply_in_entity_fetch() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t: T diff --git a/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments_preservation.rs b/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments_preservation.rs index 5633ba79b6..da90c3edb8 100644 --- a/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments_preservation.rs +++ b/apollo-federation/tests/query_plan/build_query_plan_tests/named_fragments_preservation.rs @@ -1,8 +1,16 @@ use apollo_federation::query_plan::query_planner::QueryPlannerConfig; +fn reuse_fragments_config() -> QueryPlannerConfig { + QueryPlannerConfig { + reuse_query_fragments: true, + ..Default::default() + } +} + #[test] fn it_works_with_nested_fragments_1() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { a: Anything @@ -127,6 +135,7 @@ fn it_works_with_nested_fragments_1() { #[test] fn it_avoid_fragments_usable_only_once() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t: T @@ -324,10 +333,9 @@ mod respects_query_planner_option_reuse_query_fragments { #[test] fn respects_query_planner_option_reuse_query_fragments_true() { - let reuse_query_fragments = true; let planner = planner!( - config = QueryPlannerConfig {reuse_query_fragments, ..Default::default()}, - Subgraph1: SUBGRAPH1, + config = reuse_fragments_config(), + Subgraph1: SUBGRAPH1, ); let query = QUERY; @@ -395,6 +403,7 @@ mod respects_query_planner_option_reuse_query_fragments { #[test] fn it_works_with_nested_fragments_when_only_the_nested_fragment_gets_preserved() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t: T @@ -463,6 +472,7 @@ fn it_works_with_nested_fragments_when_only_the_nested_fragment_gets_preserved() fn it_preserves_directives_when_fragment_not_used() { // (because used only once) let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t: T @@ -511,6 +521,7 @@ fn it_preserves_directives_when_fragment_not_used() { #[test] fn it_preserves_directives_when_fragment_is_reused() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t: T @@ -572,6 +583,7 @@ fn it_does_not_try_to_apply_fragments_that_are_not_valid_for_the_subgraph() { // server would reject it when validating the query, and we must make sure it // is not reused. let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { i1: I @@ -652,6 +664,7 @@ fn it_handles_fragment_rebasing_in_a_subgraph_where_some_subtyping_relation_diff // Previous versions of the code were not handling this case and were error out by // creating the invalid selection (#2721), and this test ensures this is fixed. let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type V @shareable { x: Int @@ -988,6 +1001,7 @@ fn it_handles_fragment_rebasing_in_a_subgraph_where_some_union_membership_relati // This test is similar to the subtyping case (it tests the same problems), but test the case // of unions instead of interfaces. let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type V @shareable { x: Int @@ -1302,6 +1316,7 @@ fn it_handles_fragment_rebasing_in_a_subgraph_where_some_union_membership_relati #[test] fn it_preserves_nested_fragments_when_outer_one_has_directives_and_is_eliminated() { let planner = planner!( + config = reuse_fragments_config(), Subgraph1: r#" type Query { t: T diff --git a/apollo-router-benchmarks/src/shared.rs b/apollo-router-benchmarks/src/shared.rs index cf3e57af9b..e0576c603e 100644 --- a/apollo-router-benchmarks/src/shared.rs +++ b/apollo-router-benchmarks/src/shared.rs @@ -76,7 +76,7 @@ pub fn setup() -> TestHarness<'static> { }}).build(); let review_service = MockSubgraph::builder().with_json(json!{{ - "query": "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{id product{__typename upc}author{__typename id}}}}}", + "query": "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){..._generated_onProduct1_0}}fragment _generated_onProduct1_0 on Product{reviews{id product{__typename upc}author{__typename id}}}", "operationName": "TopProducts__reviews__1", "variables": { "representations":[ diff --git a/apollo-router/src/axum_factory/snapshots/apollo_router__axum_factory__tests__defer_is_not_buffered.snap b/apollo-router/src/axum_factory/snapshots/apollo_router__axum_factory__tests__defer_is_not_buffered.snap index c08d3d1693..ece5fd3c9f 100644 --- a/apollo-router/src/axum_factory/snapshots/apollo_router__axum_factory__tests__defer_is_not_buffered.snap +++ b/apollo-router/src/axum_factory/snapshots/apollo_router__axum_factory__tests__defer_is_not_buffered.snap @@ -20,7 +20,7 @@ expression: parts }, "errors": [ { - "message": "couldn't find mock for query {\"query\":\"query($representations: [_Any!]!) { _entities(representations: $representations) { ... on Product { reviews { __typename id product { __typename upc } } } } }\",\"variables\":{\"representations\":[{\"__typename\":\"Product\",\"upc\":\"1\"},{\"__typename\":\"Product\",\"upc\":\"2\"}]}}", + "message": "couldn't find mock for query {\"query\":\"query($representations: [_Any!]!) { _entities(representations: $representations) { ..._generated_onProduct1_0 } } fragment _generated_onProduct1_0 on Product { reviews { __typename id product { __typename upc } } }\",\"variables\":{\"representations\":[{\"__typename\":\"Product\",\"upc\":\"1\"},{\"__typename\":\"Product\",\"upc\":\"2\"}]}}", "path": [ "topProducts", "@" diff --git a/apollo-router/src/axum_factory/tests.rs b/apollo-router/src/axum_factory/tests.rs index 87198b8f4f..efcf7e3ab3 100644 --- a/apollo-router/src/axum_factory/tests.rs +++ b/apollo-router/src/axum_factory/tests.rs @@ -1847,7 +1847,7 @@ async fn http_compressed_service() -> impl Service< "apollo.include_subgraph_errors": { "all": true } - } + }, })) .unwrap() .supergraph_hook(move |service| { diff --git a/apollo-router/src/configuration/mod.rs b/apollo-router/src/configuration/mod.rs index 85de05cd8f..c561a131f9 100644 --- a/apollo-router/src/configuration/mod.rs +++ b/apollo-router/src/configuration/mod.rs @@ -681,7 +681,7 @@ pub(crate) struct Supergraph { pub(crate) reuse_query_fragments: Option, /// Enable QP generation of fragments for subgraph requests - /// Default: false + /// Default: true pub(crate) generate_query_fragments: bool, /// Set to false to disable defer support @@ -701,6 +701,10 @@ pub(crate) struct Supergraph { pub(crate) experimental_log_on_broken_pipe: bool, } +const fn default_generate_query_fragments() -> bool { + true +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize, JsonSchema)] #[serde(rename_all = "snake_case", untagged)] pub(crate) enum AvailableParallelism { @@ -753,7 +757,7 @@ impl Supergraph { Some(false) } else { reuse_query_fragments } ), - generate_query_fragments: generate_query_fragments.unwrap_or_default(), + generate_query_fragments: generate_query_fragments.unwrap_or_else(default_generate_query_fragments), early_cancel: early_cancel.unwrap_or_default(), experimental_log_on_broken_pipe: experimental_log_on_broken_pipe.unwrap_or_default(), } @@ -790,7 +794,7 @@ impl Supergraph { Some(false) } else { reuse_query_fragments } ), - generate_query_fragments: generate_query_fragments.unwrap_or_default(), + generate_query_fragments: generate_query_fragments.unwrap_or_else(default_generate_query_fragments), early_cancel: early_cancel.unwrap_or_default(), experimental_log_on_broken_pipe: experimental_log_on_broken_pipe.unwrap_or_default(), } diff --git a/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap b/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap index 817d67517a..35913d1ce2 100644 --- a/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap +++ b/apollo-router/src/configuration/snapshots/apollo_router__configuration__tests__schema_generation.snap @@ -6604,8 +6604,8 @@ expression: "&schema" "type": "boolean" }, "generate_query_fragments": { - "default": false, - "description": "Enable QP generation of fragments for subgraph requests Default: false", + "default": true, + "description": "Enable QP generation of fragments for subgraph requests Default: true", "type": "boolean" }, "introspection": { diff --git a/apollo-router/src/plugin/test/mock/canned.rs b/apollo-router/src/plugin/test/mock/canned.rs index 099f494f0c..369715444e 100644 --- a/apollo-router/src/plugin/test/mock/canned.rs +++ b/apollo-router/src/plugin/test/mock/canned.rs @@ -52,7 +52,7 @@ pub(crate) fn reviews_subgraph() -> MockSubgraph { let review_mocks = vec![ ( json! {{ - "query": "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{id product{__typename upc}author{__typename id}}}}}", + "query": "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){..._generated_onProduct1_0}}fragment _generated_onProduct1_0 on Product{reviews{id product{__typename upc}author{__typename id}}}", "operationName": "TopProducts__reviews__1", "variables": { "representations":[ diff --git a/apollo-router/src/plugins/authorization/tests.rs b/apollo-router/src/plugins/authorization/tests.rs index d967125881..b8b1b8052b 100644 --- a/apollo-router/src/plugins/authorization/tests.rs +++ b/apollo-router/src/plugins/authorization/tests.rs @@ -22,7 +22,7 @@ async fn authenticated_request() { let subgraphs = MockedSubgraphs([ ("user", MockSubgraph::builder().with_json( serde_json::json!{{ - "query": "query($representations:[_Any!]!){_entities(representations:$representations){...on User{name phone}}}", + "query": "query($representations:[_Any!]!){_entities(representations:$representations){..._generated_onUser2_0}}fragment _generated_onUser2_0 on User{name phone}", "variables": { "representations": [ { "__typename": "User", "id":0 } diff --git a/apollo-router/src/plugins/cache/tests.rs b/apollo-router/src/plugins/cache/tests.rs index 64c96a0763..24dc71d3ab 100644 --- a/apollo-router/src/plugins/cache/tests.rs +++ b/apollo-router/src/plugins/cache/tests.rs @@ -160,7 +160,7 @@ async fn insert() { ).with_header(CACHE_CONTROL, HeaderValue::from_static("public")).build()), ("orga", MockSubgraph::builder().with_json( serde_json::json!{{ - "query": "query($representations:[_Any!]!){_entities(representations:$representations){...on Organization{creatorUser{__typename id}}}}", + "query": "query($representations:[_Any!]!){_entities(representations:$representations){..._generated_onOrganization1_0}}fragment _generated_onOrganization1_0 on Organization{creatorUser{__typename id}}", "variables": { "representations": [ { @@ -274,7 +274,7 @@ async fn no_cache_control() { ).build()), ("orga", MockSubgraph::builder().with_json( serde_json::json!{{ - "query": "query($representations:[_Any!]!){_entities(representations:$representations){...on Organization{creatorUser{__typename id}}}}", + "query": "query($representations:[_Any!]!){_entities(representations:$representations){..._generated_onOrganization1_0}}fragment _generated_onOrganization1_0 on Organization{creatorUser{__typename id}}", "variables": { "representations": [ { @@ -365,7 +365,7 @@ async fn private() { .build()), ("orga", MockSubgraph::builder().with_json( serde_json::json!{{ - "query": "query($representations:[_Any!]!){_entities(representations:$representations){...on Organization{creatorUser{__typename id}}}}", + "query": "query($representations:[_Any!]!){_entities(representations:$representations){..._generated_onOrganization1_0}}fragment _generated_onOrganization1_0 on Organization{creatorUser{__typename id}}", "variables": { "representations": [ { diff --git a/apollo-router/src/plugins/expose_query_plan.rs b/apollo-router/src/plugins/expose_query_plan.rs index 78d771554c..657969e27c 100644 --- a/apollo-router/src/plugins/expose_query_plan.rs +++ b/apollo-router/src/plugins/expose_query_plan.rs @@ -218,6 +218,10 @@ mod tests { build_mock_supergraph(serde_json::json! {{ "plugins": { "experimental.expose_query_plan": true + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, } }}) .await, @@ -231,6 +235,10 @@ mod tests { build_mock_supergraph(serde_json::json! {{ "plugins": { "experimental.expose_query_plan": true + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, } }}) .await, @@ -245,6 +253,10 @@ mod tests { let supergraph = build_mock_supergraph(serde_json::json! {{ "plugins": { "experimental.expose_query_plan": false + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, } }}) .await; diff --git a/apollo-router/src/plugins/include_subgraph_errors.rs b/apollo-router/src/plugins/include_subgraph_errors.rs index 34348f4ef7..3b399e0151 100644 --- a/apollo-router/src/plugins/include_subgraph_errors.rs +++ b/apollo-router/src/plugins/include_subgraph_errors.rs @@ -191,13 +191,19 @@ mod test { let product_service = MockSubgraph::new(product_mocks).with_extensions(extensions); + let mut configuration = Configuration::default(); + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + configuration.supergraph.generate_query_fragments = false; + let configuration = Arc::new(configuration); + let schema = include_str!("../../../apollo-router-benchmarks/benches/fixtures/supergraph.graphql"); - let schema = Schema::parse(schema, &Default::default()).unwrap(); + let schema = Schema::parse(schema, &configuration).unwrap(); + let planner = BridgeQueryPlannerPool::new( Vec::new(), schema.into(), - Default::default(), + Arc::clone(&configuration), NonZeroUsize::new(1).unwrap(), ) .await @@ -207,15 +213,9 @@ mod test { let builder = PluggableSupergraphServiceBuilder::new(planner); - let mut plugins = create_plugins( - &Configuration::default(), - &schema, - subgraph_schemas, - None, - None, - ) - .await - .unwrap(); + let mut plugins = create_plugins(&configuration, &schema, subgraph_schemas, None, None) + .await + .unwrap(); plugins.insert("apollo.include_subgraph_errors".to_string(), plugin); @@ -228,10 +228,10 @@ mod test { let supergraph_creator = builder.build().await.expect("should build"); RouterCreator::new( - QueryAnalysisLayer::new(supergraph_creator.schema(), Default::default()).await, - Arc::new(PersistedQueryLayer::new(&Default::default()).await.unwrap()), + QueryAnalysisLayer::new(supergraph_creator.schema(), Arc::clone(&configuration)).await, + Arc::new(PersistedQueryLayer::new(&configuration).await.unwrap()), Arc::new(supergraph_creator), - Arc::new(Configuration::default()), + configuration, ) .await .unwrap() diff --git a/apollo-router/src/plugins/traffic_shaping/mod.rs b/apollo-router/src/plugins/traffic_shaping/mod.rs index 1125239d10..4335bfe988 100644 --- a/apollo-router/src/plugins/traffic_shaping/mod.rs +++ b/apollo-router/src/plugins/traffic_shaping/mod.rs @@ -578,6 +578,9 @@ mod test { r#" traffic_shaping: deduplicate_variables: true + supergraph: + # TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + generate_query_fragments: false "#, ) .unwrap(); diff --git a/apollo-router/src/query_planner/tests.rs b/apollo-router/src/query_planner/tests.rs index 131dc7ba12..766ce9a715 100644 --- a/apollo-router/src/query_planner/tests.rs +++ b/apollo-router/src/query_planner/tests.rs @@ -821,7 +821,13 @@ async fn alias_renaming() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(schema) .extra_plugin(subgraphs) @@ -1264,7 +1270,13 @@ async fn missing_typename_and_fragments_in_requires2() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(schema) .extra_plugin(subgraphs) @@ -1551,7 +1563,13 @@ async fn typename_propagation() { ); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(TYPENAME_PROPAGATION_SCHEMA) .extra_plugin(subgraphs) @@ -1648,7 +1666,13 @@ async fn typename_propagation2() { ); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(TYPENAME_PROPAGATION_SCHEMA) .extra_plugin(subgraphs) @@ -1746,7 +1770,13 @@ async fn typename_propagation3() { ); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(TYPENAME_PROPAGATION_SCHEMA) .extra_plugin(subgraphs) diff --git a/apollo-router/src/services/router/snapshots/apollo_router__services__router__tests__escaped_quotes_in_string_literal.snap b/apollo-router/src/services/router/snapshots/apollo_router__services__router__tests__escaped_quotes_in_string_literal.snap index 9fcfad90a4..4c8165c12c 100644 --- a/apollo-router/src/services/router/snapshots/apollo_router__services__router__tests__escaped_quotes_in_string_literal.snap +++ b/apollo-router/src/services/router/snapshots/apollo_router__services__router__tests__escaped_quotes_in_string_literal.snap @@ -41,7 +41,7 @@ expression: "(graphql_response, &subgraph_query_log)" ( "reviews", Some( - "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviewsForAuthor(authorID:\"\\\"1\\\"\"){body}}}}", + "query TopProducts__reviews__1($representations:[_Any!]!){_entities(representations:$representations){..._generated_onProduct1_0}}fragment _generated_onProduct1_0 on Product{reviewsForAuthor(authorID:\"\\\"1\\\"\"){body}}", ), ), ], diff --git a/apollo-router/src/services/supergraph/tests.rs b/apollo-router/src/services/supergraph/tests.rs index b62b83737b..ac2dbab21a 100644 --- a/apollo-router/src/services/supergraph/tests.rs +++ b/apollo-router/src/services/supergraph/tests.rs @@ -655,7 +655,13 @@ async fn deferred_fragment_bounds_nullability() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(SCHEMA) .extra_plugin(subgraphs) @@ -737,7 +743,13 @@ async fn errors_on_incremental_responses() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(SCHEMA) .extra_plugin(subgraphs) @@ -809,7 +821,13 @@ async fn root_typename_with_defer() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(SCHEMA) .extra_plugin(subgraphs) @@ -867,7 +885,18 @@ async fn subscription_with_callback() { ).build()) ].into_iter().collect()); - let mut configuration: Configuration = serde_json::from_value(serde_json::json!({"include_subgraph_errors": { "all": true }, "subscription": { "enabled": true, "mode": {"callback": {"public_url": "http://localhost:4545/callback"}}}})).unwrap(); + let mut configuration: Configuration = serde_json::from_value(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "subscription": { + "enabled": true, + "mode": {"callback": {"public_url": "http://localhost:4545/callback"}} + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) + .unwrap(); configuration.notify = notify.clone(); let service = TestHarness::builder() .configuration(Arc::new(configuration)) @@ -942,7 +971,23 @@ async fn subscription_callback_schema_reload() { ("orga", orga_subgraph) ].into_iter().collect()); - let mut configuration: Configuration = serde_json::from_value(serde_json::json!({"include_subgraph_errors": { "all": true }, "headers": {"all": {"request": [{"propagate": {"named": "x-test"}}]}}, "subscription": { "enabled": true, "mode": {"callback": {"public_url": "http://localhost:4545/callback"}}}})).unwrap(); + let mut configuration: Configuration = serde_json::from_value(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "headers": { + "all": { + "request": [{"propagate": {"named": "x-test"}}] + } + }, + "subscription": { + "enabled": true, + "mode": {"callback": {"public_url": "http://localhost:4545/callback"}} + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) + .unwrap(); configuration.notify = notify.clone(); let configuration = Arc::new(configuration); let service = TestHarness::builder() @@ -1011,7 +1056,19 @@ async fn subscription_with_callback_with_limit() { ).build()) ].into_iter().collect()); - let mut configuration: Configuration = serde_json::from_value(serde_json::json!({"include_subgraph_errors": { "all": true }, "subscription": { "enabled": true, "max_opened_subscriptions": 1, "mode": {"callback": {"public_url": "http://localhost:4545/callback"}}}})).unwrap(); + let mut configuration: Configuration = serde_json::from_value(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "subscription": { + "enabled": true, + "max_opened_subscriptions": 1, + "mode": {"callback": {"public_url": "http://localhost:4545/callback"}} + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) + .unwrap(); configuration.notify = notify.clone(); let mut service = TestHarness::builder() .configuration(Arc::new(configuration)) @@ -1103,12 +1160,29 @@ async fn subscription_without_header() { async fn root_typename_with_defer_and_empty_first_response() { let subgraphs = MockedSubgraphs([ ("user", MockSubgraph::builder().with_json( - serde_json::json!{{"query":"{... on Query{currentUser{activeOrganization{__typename id}}}}"}}, - serde_json::json!{{"data": {"currentUser": { "activeOrganization": { "__typename": "Organization", "id": "0" } }}}} - ).build()), + serde_json::json!{{ + "query": " + { ..._generated_onQuery1_0 } + + fragment _generated_onQuery1_0 on Query { + currentUser { activeOrganization { __typename id} } + } + ", + }}, + serde_json::json!{{"data": {"currentUser": { "activeOrganization": { "__typename": "Organization", "id": "0" } }}}} + ).build()), ("orga", MockSubgraph::builder().with_json( serde_json::json!{{ - "query":"query($representations:[_Any!]!){_entities(representations:$representations){...on Organization{suborga{id name}}}}", + "query": " + query($representations: [_Any!]!) { + _entities(representations: $representations) { + ..._generated_onOrganization1_0 + } + } + fragment _generated_onOrganization1_0 on Organization { + suborga { id name } + } + ", "variables": { "representations":[{"__typename": "Organization", "id":"0"}] } @@ -1216,7 +1290,14 @@ async fn root_typename_with_defer_in_defer() { ).build()), ("orga", MockSubgraph::builder().with_json( serde_json::json!{{ - "query":"query($representations:[_Any!]!){_entities(representations:$representations){...on Organization{suborga{__typename id name}}}}", + "query":" + query($representations:[_Any!]!){ + _entities(representations:$representations) { ..._generated_onOrganization1_0 } + } + fragment _generated_onOrganization1_0 on Organization { + suborga {__typename id name} + } + ", "variables": { "representations":[{"__typename": "Organization", "id":"0"}] } @@ -1453,7 +1534,13 @@ async fn filter_nullified_deferred_responses() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(SCHEMA) .extra_plugin(subgraphs) @@ -1606,7 +1693,13 @@ async fn reconstruct_deferred_query_under_interface() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(schema) .extra_plugin(subgraphs) @@ -1775,7 +1868,13 @@ async fn interface_object_typename_rewrites() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(schema) .extra_plugin(subgraphs) @@ -1913,7 +2012,13 @@ async fn interface_object_response_processing() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(schema) .extra_plugin(subgraphs) @@ -2182,7 +2287,13 @@ async fn aliased_subgraph_data_rewrites_on_root_fetch() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(schema) .extra_plugin(subgraphs) @@ -2322,7 +2433,13 @@ async fn aliased_subgraph_data_rewrites_on_non_root_fetch() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, + } + })) .unwrap() .schema(schema) .extra_plugin(subgraphs) @@ -3295,7 +3412,13 @@ async fn fragment_reuse() { ].into_iter().collect()); let service = TestHarness::builder() - .configuration_json(serde_json::json!({"include_subgraph_errors": { "all": true } })) + .configuration_json(serde_json::json!({ + "include_subgraph_errors": { "all": true }, + "supergraph": { + "generate_query_fragments": false, + "experimental_reuse_query_fragments": true, + } + })) .unwrap() .schema(SCHEMA) .extra_plugin(subgraphs) diff --git a/apollo-router/tests/fixtures/type_conditions/artwork.json b/apollo-router/tests/fixtures/type_conditions/artwork.json index ad5451f398..e4c437c2cd 100644 --- a/apollo-router/tests/fixtures/type_conditions/artwork.json +++ b/apollo-router/tests/fixtures/type_conditions/artwork.json @@ -2,7 +2,7 @@ "mocks": [ { "request": { - "query":"query Search__artworkSubgraph__1($representations:[_Any!]!$movieResultParam:String){_entities(representations:$representations){...on EntityCollectionSection{title artwork(params:$movieResultParam)}...on GallerySection{artwork(params:$movieResultParam)}}}", + "query":"query Search__artworkSubgraph__1($representations:[_Any!]!$movieResultParam:String){_entities(representations:$representations){..._generated_onEntityCollectionSection2_0 ...on GallerySection{artwork(params:$movieResultParam)}}}fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection{title artwork(params:$movieResultParam)}", "operationName":"Search__artworkSubgraph__1", "variables":{ "movieResultParam":"movieResultEnabled", @@ -50,7 +50,7 @@ }, { "request": { - "query": "query Search__artworkSubgraph__2($representations:[_Any!]!$articleResultParam:String){_entities(representations:$representations){...on GallerySection{artwork(params:$articleResultParam)}...on EntityCollectionSection{artwork(params:$articleResultParam)title}}}", + "query": "query Search__artworkSubgraph__2($representations:[_Any!]!$articleResultParam:String){_entities(representations:$representations){...on GallerySection{artwork(params:$articleResultParam)}..._generated_onEntityCollectionSection2_0}}fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection{artwork(params:$articleResultParam)title}", "operationName": "Search__artworkSubgraph__2", "variables":{ "articleResultParam":"articleResultEnabled", diff --git a/apollo-router/tests/fixtures/type_conditions/artwork_disabled.json b/apollo-router/tests/fixtures/type_conditions/artwork_disabled.json index 1552804424..5e230e1e3c 100644 --- a/apollo-router/tests/fixtures/type_conditions/artwork_disabled.json +++ b/apollo-router/tests/fixtures/type_conditions/artwork_disabled.json @@ -2,7 +2,7 @@ "mocks": [ { "request": { - "query":"query Search__artworkSubgraph__1($representations:[_Any!]!$movieResultParam:String){_entities(representations:$representations){...on EntityCollectionSection{title artwork(params:$movieResultParam)}...on GallerySection{artwork(params:$movieResultParam)}}}", + "query":"query Search__artworkSubgraph__1($representations:[_Any!]!$movieResultParam:String){_entities(representations:$representations){..._generated_onEntityCollectionSection2_0...on GallerySection{artwork(params:$movieResultParam)}}}fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection{title artwork(params:$movieResultParam)}", "operationName":"Search__artworkSubgraph__1", "variables":{ "representations":[ @@ -79,4 +79,4 @@ } } ] -} \ No newline at end of file +} diff --git a/apollo-router/tests/fixtures/type_conditions/search.json b/apollo-router/tests/fixtures/type_conditions/search.json index 1393fcfd02..85bc7facaa 100644 --- a/apollo-router/tests/fixtures/type_conditions/search.json +++ b/apollo-router/tests/fixtures/type_conditions/search.json @@ -2,7 +2,7 @@ "mocks": [ { "request": { - "query":"query Search__searchSubgraph__0{search{__typename ...on MovieResult{sections{__typename ...on EntityCollectionSection{__typename id}...on GallerySection{__typename id}}id}...on ArticleResult{id sections{__typename ...on GallerySection{__typename id}...on EntityCollectionSection{__typename id}}}}}", + "query":"query Search__searchSubgraph__0{search{__typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0}}fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection{__typename id}fragment _generated_onGallerySection2_0 on GallerySection{__typename id}fragment _generated_onMovieResult2_0 on MovieResult{sections{__typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0}id}fragment _generated_onArticleResult2_0 on ArticleResult{id sections{__typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0}}", "operationName":"Search__searchSubgraph__0" }, "response": { diff --git a/apollo-router/tests/fixtures/type_conditions/search_list_of_list.json b/apollo-router/tests/fixtures/type_conditions/search_list_of_list.json index 228e4ab0db..6197584e2b 100644 --- a/apollo-router/tests/fixtures/type_conditions/search_list_of_list.json +++ b/apollo-router/tests/fixtures/type_conditions/search_list_of_list.json @@ -2,7 +2,7 @@ "mocks": [ { "request": { - "query":"query Search__searchSubgraph__0{searchListOfList{__typename ...on MovieResult{sections{__typename ...on EntityCollectionSection{__typename id}...on GallerySection{__typename id}}id}...on ArticleResult{id sections{__typename ...on GallerySection{__typename id}...on EntityCollectionSection{__typename id}}}}}", + "query": "query Search__searchSubgraph__0 { searchListOfList { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName":"Search__searchSubgraph__0" }, "response": { @@ -133,4 +133,4 @@ } } ] -} \ No newline at end of file +} diff --git a/apollo-router/tests/fixtures/type_conditions/search_list_of_list_of_list.json b/apollo-router/tests/fixtures/type_conditions/search_list_of_list_of_list.json index 1c2023c5ec..e183b3e65c 100644 --- a/apollo-router/tests/fixtures/type_conditions/search_list_of_list_of_list.json +++ b/apollo-router/tests/fixtures/type_conditions/search_list_of_list_of_list.json @@ -2,7 +2,7 @@ "mocks": [ { "request": { - "query":"query Search__searchSubgraph__0{searchListOfListOfList{__typename ...on MovieResult{sections{__typename ...on EntityCollectionSection{__typename id}...on GallerySection{__typename id}}id}...on ArticleResult{id sections{__typename ...on GallerySection{__typename id}...on EntityCollectionSection{__typename id}}}}}", + "query":"query Search__searchSubgraph__0 { searchListOfListOfList { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName":"Search__searchSubgraph__0" }, "response": { @@ -137,4 +137,4 @@ } } ] -} \ No newline at end of file +} diff --git a/apollo-router/tests/integration/fixtures/query_planner_redis_config_update_query_fragments.router.yaml b/apollo-router/tests/integration/fixtures/query_planner_redis_config_update_query_fragments.router.yaml index ffb1e49152..e2232cb331 100644 --- a/apollo-router/tests/integration/fixtures/query_planner_redis_config_update_query_fragments.router.yaml +++ b/apollo-router/tests/integration/fixtures/query_planner_redis_config_update_query_fragments.router.yaml @@ -1,4 +1,4 @@ -# This config updates the query plan options so that we can see if there is a different redis cache entry generted for query plans +# This config updates the query plan options so that we can see if there is a different redis cache entry generated for query plans supergraph: query_planning: cache: @@ -7,5 +7,5 @@ supergraph: urls: - redis://localhost:6379 ttl: 10s - generate_query_fragments: true + generate_query_fragments: false diff --git a/apollo-router/tests/integration/redis.rs b/apollo-router/tests/integration/redis.rs index ff42bf8d7e..955cbc9290 100644 --- a/apollo-router/tests/integration/redis.rs +++ b/apollo-router/tests/integration/redis.rs @@ -51,7 +51,7 @@ async fn query_planner_cache() -> Result<(), BoxError> { } // If this test fails and the cache key format changed you'll need to update the key here. // Look at the top of the file for instructions on getting the new cache key. - let known_cache_key = "plan:cache:1:federation:v2.9.3:70f115ebba5991355c17f4f56ba25bb093c519c4db49a30f3b10de279a4e3fa4:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:0ade8e18db172d9d51b36a2112513c15032d103100644df418a50596de3adfba"; + let known_cache_key = "plan:cache:1:federation:v2.9.3:70f115ebba5991355c17f4f56ba25bb093c519c4db49a30f3b10de279a4e3fa4:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:1cfc840090ac76a98f8bd51442f41fd6ca4c8d918b3f8d87894170745acf0734"; let config = RedisConfig::from_url("redis://127.0.0.1:6379").unwrap(); let client = RedisClient::new(config, None, None, None); @@ -420,6 +420,10 @@ async fn entity_cache_basic() -> Result<(), BoxError> { }, "include_subgraph_errors": { "all": true + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, } })) .unwrap() @@ -534,6 +538,10 @@ async fn entity_cache_basic() -> Result<(), BoxError> { }, "include_subgraph_errors": { "all": true + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, } })) .unwrap() @@ -750,6 +758,10 @@ async fn entity_cache_authorization() -> Result<(), BoxError> { }, "include_subgraph_errors": { "all": true + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, } })) .unwrap() @@ -962,8 +974,9 @@ async fn connection_failure_blocks_startup() { #[tokio::test(flavor = "multi_thread")] async fn query_planner_redis_update_query_fragments() { test_redis_query_plan_config_update( + // This configuration turns the fragment generation option *off*. include_str!("fixtures/query_planner_redis_config_update_query_fragments.router.yaml"), - "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:1cfc840090ac76a98f8bd51442f41fd6ca4c8d918b3f8d87894170745acf0734", + "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:0ade8e18db172d9d51b36a2112513c15032d103100644df418a50596de3adfba", ) .await; } @@ -993,7 +1006,7 @@ async fn query_planner_redis_update_defer() { // test just passes locally. test_redis_query_plan_config_update( include_str!("fixtures/query_planner_redis_config_update_defer.router.yaml"), - "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:2f7fb939d2a8fc978e5a4e9d17998074fc30366dcc673236237a885819084fc0", + "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:066f41523274aed2428e0f08c9de077ee748a1d8470ec31edb5224030a198f3b", ) .await; } @@ -1015,7 +1028,7 @@ async fn query_planner_redis_update_type_conditional_fetching() { include_str!( "fixtures/query_planner_redis_config_update_type_conditional_fetching.router.yaml" ), - "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:0fd0a376f59f0565768ea5ad8eadfbbf60d64c593c807457a0776d2f39773a25", + "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:b31d320db1af4015998cc89027f0ede2305dcc61724365e9b76d4252f90c7677", ) .await; } @@ -1037,7 +1050,7 @@ async fn query_planner_redis_update_reuse_query_fragments() { include_str!( "fixtures/query_planner_redis_config_update_reuse_query_fragments.router.yaml" ), - "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:3f30f0e2d149d00c9370c8046e4dd5f23d6ceb6f05a6cf06d5eb021510564248", + "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:d54414eeede3a1bf631d88a84a1e3a354683be87746e79a69769cf18d919cc01", ) .await; } @@ -1061,8 +1074,7 @@ async fn test_redis_query_plan_config_update(updated_config: &str, new_cache_key router.assert_started().await; router.clear_redis_cache().await; - // If the tests above are failing, this is the key that needs to be changed first. - let starting_key = "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:0ade8e18db172d9d51b36a2112513c15032d103100644df418a50596de3adfba"; + let starting_key = "plan:cache:1:federation:v2.9.3:e15b4f5cd51b8cc728e3f5171611073455601e81196cd3cbafc5610d9769a370:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:1cfc840090ac76a98f8bd51442f41fd6ca4c8d918b3f8d87894170745acf0734"; assert_ne!(starting_key, new_cache_key, "starting_key (cache key for the initial config) and new_cache_key (cache key with the updated config) should not be equal. This either means that the cache key is not being generated correctly, or that the test is not actually checking the updated key."); router.execute_default_query().await; diff --git a/apollo-router/tests/samples/core/defer/plan.json b/apollo-router/tests/samples/core/defer/plan.json index b2499400bd..72dd5efed0 100644 --- a/apollo-router/tests/samples/core/defer/plan.json +++ b/apollo-router/tests/samples/core/defer/plan.json @@ -32,7 +32,7 @@ { "request": { "body": { - "query": "query($representations:[_Any!]!){_entities(representations:$representations){...on User{reviews{body}}}}", + "query": "query($representations:[_Any!]!){_entities(representations:$representations){..._generated_onUser1_0}}fragment _generated_onUser1_0 on User{reviews{body}}", "variables": { "representations": [ { @@ -103,4 +103,4 @@ "type": "Stop" } ] -} \ No newline at end of file +} diff --git a/apollo-router/tests/samples/enterprise/entity-cache/defer/plan.json b/apollo-router/tests/samples/enterprise/entity-cache/defer/plan.json index 265e282056..83a777d329 100644 --- a/apollo-router/tests/samples/enterprise/entity-cache/defer/plan.json +++ b/apollo-router/tests/samples/enterprise/entity-cache/defer/plan.json @@ -39,7 +39,7 @@ { "request": { "body": { - "query": "query CacheDefer__cache_defer_reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on User{reviews{body}}}}", + "query": "query CacheDefer__cache_defer_reviews__1($representations:[_Any!]!){_entities(representations:$representations){..._generated_onUser1_0}}fragment _generated_onUser1_0 on User{reviews{body}}", "operationName": "CacheDefer__cache_defer_reviews__1", "variables": { "representations": [ @@ -110,4 +110,4 @@ "type": "Stop" } ] -} \ No newline at end of file +} diff --git a/apollo-router/tests/samples/enterprise/entity-cache/invalidation-entity-key/plan.json b/apollo-router/tests/samples/enterprise/entity-cache/invalidation-entity-key/plan.json index 1bb1bc0210..c8588ed2b7 100644 --- a/apollo-router/tests/samples/enterprise/entity-cache/invalidation-entity-key/plan.json +++ b/apollo-router/tests/samples/enterprise/entity-cache/invalidation-entity-key/plan.json @@ -31,7 +31,7 @@ { "request": { "body": { - "query":"query InvalidationEntityKey__invalidation_entity_key_reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{body}}}}", + "query":"query InvalidationEntityKey__invalidation_entity_key_reviews__1($representations:[_Any!]!){_entities(representations:$representations){..._generated_onProduct1_0}}fragment _generated_onProduct1_0 on Product{reviews{body}}", "operationName": "InvalidationEntityKey__invalidation_entity_key_reviews__1", "variables":{"representations":[{"upc":"0","__typename":"Product"},{"upc":"1","__typename":"Product"}]} } @@ -115,7 +115,7 @@ { "request": { "body": { - "query":"query InvalidationEntityKey__invalidation_entity_key_reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{body}}}}", + "query":"query InvalidationEntityKey__invalidation_entity_key_reviews__1($representations:[_Any!]!){_entities(representations:$representations){..._generated_onProduct1_0}}fragment _generated_onProduct1_0 on Product{reviews{body}}", "variables":{"representations":[{"upc":"1","__typename":"Product"}]} } }, @@ -202,7 +202,7 @@ { "request": { "body": { - "query":"query InvalidationEntityKey__invalidation_entity_key_reviews__1($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{body}}}}", + "query":"query InvalidationEntityKey__invalidation_entity_key_reviews__1($representations:[_Any!]!){_entities(representations:$representations){..._generated_onProduct1_0}}fragment _generated_onProduct1_0 on Product{reviews{body}}", "variables":{"representations":[{"upc":"1","__typename":"Product"}]} } }, @@ -250,4 +250,4 @@ "type": "Stop" } ] -} \ No newline at end of file +} diff --git a/apollo-router/tests/set_context.rs b/apollo-router/tests/set_context.rs index 47d8deb076..aae8107137 100644 --- a/apollo-router/tests/set_context.rs +++ b/apollo-router/tests/set_context.rs @@ -42,6 +42,10 @@ async fn run_single_request(query: &str, mocks: &[(&'static str, &'static str)]) }, "include_subgraph_errors": { "all": true + }, + "supergraph": { + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "generate_query_fragments": false, } }}, mocks, diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled-2.snap index 17f0ec285c..390a7c79df 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled-2.snap @@ -72,14 +72,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { search { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { search { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "587c887350ef75eaf4b647be94fd682616bcd33909e15fb797cee226e95fa36a", + "schemaAwareHash": "70ca85b28e861b24a7749862930a5f965c4c6e8074d60a87a3952d596fe7cc36", "authorization": { "is_authenticated": false, "scopes": [], @@ -130,14 +130,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "622eb49d4e52ff2636348e103f941d04b783fec97de59d0ae6635d9272f97ad8", + "schemaAwareHash": "317a722a677563080aeac92f60ac2257d9288ca6851a0e8980fcf18f58b462a8", "authorization": { "is_authenticated": false, "scopes": [], @@ -148,7 +148,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Flatten(path: \"search.@.sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n\n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n\n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n\n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Flatten(path: \"search.@.sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled.snap index f355685192..687028717f 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_disabled.snap @@ -72,14 +72,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { search { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { search { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5201830580c9c5fadd9c59aea072878f84465c1ae9d905207fa281aa7c1d5340", + "schemaAwareHash": "0e1644746fe4beab7def35ec8cc12bde39874c6bb8b9dfd928456196b814a111", "authorization": { "is_authenticated": false, "scopes": [], @@ -130,14 +130,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "62ff891f6971184d3e42b98f8166be72027b5479f9ec098af460a48ea6f6cbf4", + "schemaAwareHash": "6510f6b9672829bd9217618b78ef6f329fbddb125f88184d04e6faaa982ff8bb", "authorization": { "is_authenticated": false, "scopes": [], @@ -148,7 +148,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Flatten(path: \"search.@.sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n \n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n \n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n \n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Flatten(path: \"search.@.sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled-2.snap index 01e49a0721..ed94ed7a85 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled-2.snap @@ -72,14 +72,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { search { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { search { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "587c887350ef75eaf4b647be94fd682616bcd33909e15fb797cee226e95fa36a", + "schemaAwareHash": "70ca85b28e861b24a7749862930a5f965c4c6e8074d60a87a3952d596fe7cc36", "authorization": { "is_authenticated": false, "scopes": [], @@ -133,14 +133,14 @@ expression: response "variableUsages": [ "articleResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ... on EntityCollectionSection { artwork(params: $articleResultParam) title } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ..._generated_onEntityCollectionSection2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { artwork(params: $articleResultParam) title }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "a0bf36d3a611df53c3a60b9b124a2887f2d266858221c606ace0985d101d64bd", + "schemaAwareHash": "1d21a65a3b5a31e17f7834750ef5b37fb49d99d0a1e2145f00a62d43c5f8423a", "authorization": { "is_authenticated": false, "scopes": [], @@ -192,14 +192,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__2", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3e84a53f967bf40d4c08254a94f3fa32a828ab3ad8184a22bb3439c596ecaaf4", + "schemaAwareHash": "df321f6532c2c9eda0d8c042e5f08073c24e558dd0cae01054886b79416a6c08", "authorization": { "is_authenticated": false, "scopes": [], @@ -212,7 +212,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Parallel {\n Flatten(path: \"search.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ... on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n }\n },\n },\n Flatten(path: \"search.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n\n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n\n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n\n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Parallel {\n Flatten(path: \"search.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ..._generated_onEntityCollectionSection2_0\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n },\n },\n Flatten(path: \"search.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled.snap index a8afd1fa0e..08a9782c85 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled.snap @@ -72,14 +72,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { search { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { search { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5201830580c9c5fadd9c59aea072878f84465c1ae9d905207fa281aa7c1d5340", + "schemaAwareHash": "0e1644746fe4beab7def35ec8cc12bde39874c6bb8b9dfd928456196b814a111", "authorization": { "is_authenticated": false, "scopes": [], @@ -134,14 +134,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "62ff891f6971184d3e42b98f8166be72027b5479f9ec098af460a48ea6f6cbf4", + "schemaAwareHash": "6510f6b9672829bd9217618b78ef6f329fbddb125f88184d04e6faaa982ff8bb", "authorization": { "is_authenticated": false, "scopes": [], @@ -194,14 +194,14 @@ expression: response "variableUsages": [ "articleResultParam" ], - "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ... on EntityCollectionSection { artwork(params: $articleResultParam) title } } }", + "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ..._generated_onEntityCollectionSection2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { artwork(params: $articleResultParam) title }", "operationName": "Search__artworkSubgraph__2", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7e6f6850777335eb1421a30a45f6888bb9e5d0acf8f55d576d55d1c4b7d23ec7", + "schemaAwareHash": "6bc34c108f7cf81896971bffad76dc5275d46231b4dfe492ccc205dda9a4aa16", "authorization": { "is_authenticated": false, "scopes": [], @@ -214,7 +214,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Parallel {\n Flatten(path: \".search.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n Flatten(path: \".search.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ... on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n }\n },\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n search {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n \n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n \n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n \n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Parallel {\n Flatten(path: \".search.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n Flatten(path: \".search.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ..._generated_onEntityCollectionSection2_0\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n },\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list-2.snap index c990725153..fc5007829d 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list-2.snap @@ -134,14 +134,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { searchListOfList { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { searchListOfList { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "365685f6b9f1c5dd02506b27f50d63486f1ca6b5ced7b0253fc050ef73732e03", + "schemaAwareHash": "ff18ff586aee784ec507117854cb4b64f9693d528df1ee69c922b5d75ae637fb", "authorization": { "is_authenticated": false, "scopes": [], @@ -196,14 +196,14 @@ expression: response "variableUsages": [ "articleResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ... on EntityCollectionSection { artwork(params: $articleResultParam) title } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ..._generated_onEntityCollectionSection2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { artwork(params: $articleResultParam) title }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "a0bf36d3a611df53c3a60b9b124a2887f2d266858221c606ace0985d101d64bd", + "schemaAwareHash": "1d21a65a3b5a31e17f7834750ef5b37fb49d99d0a1e2145f00a62d43c5f8423a", "authorization": { "is_authenticated": false, "scopes": [], @@ -256,14 +256,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__2", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3e84a53f967bf40d4c08254a94f3fa32a828ab3ad8184a22bb3439c596ecaaf4", + "schemaAwareHash": "df321f6532c2c9eda0d8c042e5f08073c24e558dd0cae01054886b79416a6c08", "authorization": { "is_authenticated": false, "scopes": [], @@ -276,7 +276,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfList {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Parallel {\n Flatten(path: \"searchListOfList.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ... on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n }\n },\n },\n Flatten(path: \"searchListOfList.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfList {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n\n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n\n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n\n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Parallel {\n Flatten(path: \"searchListOfList.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ..._generated_onEntityCollectionSection2_0\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n },\n },\n Flatten(path: \"searchListOfList.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list.snap index adf981893a..4c219874d6 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list.snap @@ -134,14 +134,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { searchListOfList { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { searchListOfList { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "51a7aadec14b66d9f6c737be7418bac0be1af89fcc55dac55d9e9b125bc3682d", + "schemaAwareHash": "70b62e564b3924984694d90de2b10947a2f5c14ceb76d154f43bb3c638c4830b", "authorization": { "is_authenticated": false, "scopes": [], @@ -197,14 +197,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "62ff891f6971184d3e42b98f8166be72027b5479f9ec098af460a48ea6f6cbf4", + "schemaAwareHash": "6510f6b9672829bd9217618b78ef6f329fbddb125f88184d04e6faaa982ff8bb", "authorization": { "is_authenticated": false, "scopes": [], @@ -258,14 +258,14 @@ expression: response "variableUsages": [ "articleResultParam" ], - "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ... on EntityCollectionSection { artwork(params: $articleResultParam) title } } }", + "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ..._generated_onEntityCollectionSection2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { artwork(params: $articleResultParam) title }", "operationName": "Search__artworkSubgraph__2", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7e6f6850777335eb1421a30a45f6888bb9e5d0acf8f55d576d55d1c4b7d23ec7", + "schemaAwareHash": "6bc34c108f7cf81896971bffad76dc5275d46231b4dfe492ccc205dda9a4aa16", "authorization": { "is_authenticated": false, "scopes": [], @@ -278,7 +278,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfList {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Parallel {\n Flatten(path: \".searchListOfList.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n Flatten(path: \".searchListOfList.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ... on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n }\n },\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfList {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n \n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n \n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n \n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Parallel {\n Flatten(path: \".searchListOfList.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n Flatten(path: \".searchListOfList.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ..._generated_onEntityCollectionSection2_0\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n },\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list-2.snap index f206e94c89..5cc97759df 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list-2.snap @@ -138,14 +138,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { searchListOfListOfList { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { searchListOfListOfList { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "47d7643dd7226529814a57e0382aafb3790c2d8a8b26354aa2f60e9c9f097a05", + "schemaAwareHash": "cb374f6eaa19cb529eeae258f2b136dbc751e3784fdc279954e59622cfb1edde", "authorization": { "is_authenticated": false, "scopes": [], @@ -201,14 +201,14 @@ expression: response "variableUsages": [ "articleResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ... on EntityCollectionSection { artwork(params: $articleResultParam) title } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ..._generated_onEntityCollectionSection2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { artwork(params: $articleResultParam) title }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "a0bf36d3a611df53c3a60b9b124a2887f2d266858221c606ace0985d101d64bd", + "schemaAwareHash": "1d21a65a3b5a31e17f7834750ef5b37fb49d99d0a1e2145f00a62d43c5f8423a", "authorization": { "is_authenticated": false, "scopes": [], @@ -262,14 +262,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__2", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3e84a53f967bf40d4c08254a94f3fa32a828ab3ad8184a22bb3439c596ecaaf4", + "schemaAwareHash": "df321f6532c2c9eda0d8c042e5f08073c24e558dd0cae01054886b79416a6c08", "authorization": { "is_authenticated": false, "scopes": [], @@ -282,7 +282,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfListOfList {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Parallel {\n Flatten(path: \"searchListOfListOfList.@.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ... on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n }\n },\n },\n Flatten(path: \"searchListOfListOfList.@.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfListOfList {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n\n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n\n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n\n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Parallel {\n Flatten(path: \"searchListOfListOfList.@.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ..._generated_onEntityCollectionSection2_0\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n },\n },\n Flatten(path: \"searchListOfListOfList.@.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n\n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list.snap index 78a539ec02..593bd573f6 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_list_of_list_of_list.snap @@ -138,14 +138,14 @@ expression: response "kind": "Fetch", "serviceName": "searchSubgraph", "variableUsages": [], - "operation": "query Search__searchSubgraph__0 { searchListOfListOfList { __typename ... on MovieResult { sections { __typename ... on EntityCollectionSection { __typename id } ... on GallerySection { __typename id } } id } ... on ArticleResult { id sections { __typename ... on GallerySection { __typename id } ... on EntityCollectionSection { __typename id } } } } }", + "operation": "query Search__searchSubgraph__0 { searchListOfListOfList { __typename ..._generated_onMovieResult2_0 ..._generated_onArticleResult2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { __typename id } fragment _generated_onGallerySection2_0 on GallerySection { __typename id } fragment _generated_onMovieResult2_0 on MovieResult { sections { __typename ..._generated_onEntityCollectionSection2_0 ..._generated_onGallerySection2_0 } id } fragment _generated_onArticleResult2_0 on ArticleResult { id sections { __typename ..._generated_onGallerySection2_0 ..._generated_onEntityCollectionSection2_0 } }", "operationName": "Search__searchSubgraph__0", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "e6f45a784fb669930586f13fc587f55798089a87ee4b23a7d1736e0516367a6a", + "schemaAwareHash": "26ae1da614855e4edee344061c0fc95ec4613a99e012de1f33207cb5318487b8", "authorization": { "is_authenticated": false, "scopes": [], @@ -202,14 +202,14 @@ expression: response "variableUsages": [ "movieResultParam" ], - "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ... on EntityCollectionSection { title artwork(params: $movieResultParam) } ... on GallerySection { artwork(params: $movieResultParam) } } }", + "operation": "query Search__artworkSubgraph__1($representations: [_Any!]!, $movieResultParam: String) { _entities(representations: $representations) { ..._generated_onEntityCollectionSection2_0 ... on GallerySection { artwork(params: $movieResultParam) } } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { title artwork(params: $movieResultParam) }", "operationName": "Search__artworkSubgraph__1", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "62ff891f6971184d3e42b98f8166be72027b5479f9ec098af460a48ea6f6cbf4", + "schemaAwareHash": "6510f6b9672829bd9217618b78ef6f329fbddb125f88184d04e6faaa982ff8bb", "authorization": { "is_authenticated": false, "scopes": [], @@ -264,14 +264,14 @@ expression: response "variableUsages": [ "articleResultParam" ], - "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ... on EntityCollectionSection { artwork(params: $articleResultParam) title } } }", + "operation": "query Search__artworkSubgraph__2($representations: [_Any!]!, $articleResultParam: String) { _entities(representations: $representations) { ... on GallerySection { artwork(params: $articleResultParam) } ..._generated_onEntityCollectionSection2_0 } } fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection { artwork(params: $articleResultParam) title }", "operationName": "Search__artworkSubgraph__2", "operationKind": "query", "id": null, "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7e6f6850777335eb1421a30a45f6888bb9e5d0acf8f55d576d55d1c4b7d23ec7", + "schemaAwareHash": "6bc34c108f7cf81896971bffad76dc5275d46231b4dfe492ccc205dda9a4aa16", "authorization": { "is_authenticated": false, "scopes": [], @@ -284,7 +284,7 @@ expression: response ] } }, - "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfListOfList {\n __typename\n ... on MovieResult {\n sections {\n __typename\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n }\n id\n }\n ... on ArticleResult {\n id\n sections {\n __typename\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n }\n }\n }\n }\n },\n Parallel {\n Flatten(path: \".searchListOfListOfList.@.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ... on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n },\n },\n Flatten(path: \".searchListOfListOfList.@.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ... on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n }\n },\n },\n },\n },\n}" + "text": "QueryPlan {\n Sequence {\n Fetch(service: \"searchSubgraph\") {\n {\n searchListOfListOfList {\n __typename\n ..._generated_onMovieResult2_0\n ..._generated_onArticleResult2_0\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n __typename\n id\n }\n \n fragment _generated_onGallerySection2_0 on GallerySection {\n __typename\n id\n }\n \n fragment _generated_onMovieResult2_0 on MovieResult {\n sections {\n __typename\n ..._generated_onEntityCollectionSection2_0\n ..._generated_onGallerySection2_0\n }\n id\n }\n \n fragment _generated_onArticleResult2_0 on ArticleResult {\n id\n sections {\n __typename\n ..._generated_onGallerySection2_0\n ..._generated_onEntityCollectionSection2_0\n }\n }\n },\n Parallel {\n Flatten(path: \".searchListOfListOfList.@.@.@|[MovieResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on EntityCollectionSection {\n __typename\n id\n }\n ... on GallerySection {\n __typename\n id\n }\n } =>\n {\n ..._generated_onEntityCollectionSection2_0\n ... on GallerySection {\n artwork(params: $movieResultParam)\n }\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n title\n artwork(params: $movieResultParam)\n }\n },\n },\n Flatten(path: \".searchListOfListOfList.@.@.@|[ArticleResult].sections.@\") {\n Fetch(service: \"artworkSubgraph\") {\n {\n ... on GallerySection {\n __typename\n id\n }\n ... on EntityCollectionSection {\n __typename\n id\n }\n } =>\n {\n ... on GallerySection {\n artwork(params: $articleResultParam)\n }\n ..._generated_onEntityCollectionSection2_0\n }\n \n fragment _generated_onEntityCollectionSection2_0 on EntityCollectionSection {\n artwork(params: $articleResultParam)\n title\n }\n },\n },\n },\n },\n}" } } } diff --git a/apollo-router/tests/tracing_common/mod.rs b/apollo-router/tests/tracing_common/mod.rs index 0eda97f796..f7f698b87f 100644 --- a/apollo-router/tests/tracing_common/mod.rs +++ b/apollo-router/tests/tracing_common/mod.rs @@ -426,7 +426,15 @@ pub(crate) fn subgraph_mocks(subgraph: &str) -> subgraph::BoxService { }; builder.with_json( json!({ - "query": "query($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{author{__typename id}}}}}", + "query": " + query($representations: [_Any!]!) { + _entities(representations: $representations) { + ..._generated_onProduct1_0 + } + } + fragment _generated_onProduct1_0 on Product { + reviews { author{ __typename id } } + }", "variables": {"representations": [ {"__typename": "Product", "upc": "1"}, {"__typename": "Product", "upc": "2"}, diff --git a/apollo-router/tests/type_conditions.rs b/apollo-router/tests/type_conditions.rs index 88757228b8..ab43b3f521 100644 --- a/apollo-router/tests/type_conditions.rs +++ b/apollo-router/tests/type_conditions.rs @@ -118,9 +118,6 @@ async fn _test_type_conditions_enabled_generate_query_fragments(planner_mode: &s json! {{ "experimental_type_conditioned_fetching": true, "experimental_query_planner_mode": planner_mode, - "supergraph": { - "generate_query_fragments": true - }, // will make debugging easier "plugins": { "experimental.expose_query_plan": true @@ -321,6 +318,10 @@ async fn _test_type_conditions_enabled_shouldnt_make_article_fetch(planner_mode: "plugins": { "experimental.expose_query_plan": true }, + // TODO(@goto-bus-stop): need to update the mocks and remove this, #6013 + "supergraph": { + "generate_query_fragments": false, + }, "include_subgraph_errors": { "all": true } diff --git a/docs/source/reference/router/configuration.mdx b/docs/source/reference/router/configuration.mdx index 3c89326a73..42597a9e57 100644 --- a/docs/source/reference/router/configuration.mdx +++ b/docs/source/reference/router/configuration.mdx @@ -1236,22 +1236,29 @@ example: password: "${env.MY_PASSWORD}" #highlight-line ``` -### Fragment reuse and generation + + +### Fragment generation and reuse -By default, the 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`: +By default, the router compresses subgraph requests by generating fragment +definitions based on the shape of the subgraph operation. In many cases this +significantly reduces the size of the query sent to subgraphs. -```yaml -supergraph: - experimental_reuse_query_fragments: false -``` - -Alternatively, the router can be configured to _generate_ fragments for subgraph requests. When set to `true`, the 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. +The router also supports an experimental algorithm that attempts to reuse fragments +from the original operation while forming subgraph requests. This experimental feature +used to be enabled by default, but is still available to support subgraphs that rely +on the specific shape of fragments in an operation: ```yaml supergraph: - generate_query_fragments: true + generate_query_fragments: false + experimental_reuse_query_fragments: true ``` +Note that `generate_query_fragments` and `experimental_reuse_query_fragments` are +mutually exclusive; if both are explicitly set to `true`, `generate_query_fragments` +will take precedence. + In the future, the `generate_query_fragments` option will be the only option for handling fragments. From defd699fe2345865c4f315e42635029db40f50da Mon Sep 17 00:00:00 2001 From: Andrew Carlson <5479270+andrewicarlson@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:09:32 -0600 Subject: [PATCH 3/8] Fixed an issue with the formatting of the Entity Cache Invalidation diagram --- docs/source/routing/performance/caching/entity.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/source/routing/performance/caching/entity.mdx b/docs/source/routing/performance/caching/entity.mdx index d251c19e7e..db9c5772e5 100644 --- a/docs/source/routing/performance/caching/entity.mdx +++ b/docs/source/routing/performance/caching/entity.mdx @@ -216,7 +216,6 @@ This entry contains an object with the `all` field to affect all subgraph reques ### Entity cache invalidation ```mermaid -%%{init: {"flowchart": {"htmlLabels": false}} }%% flowchart RL subgraph QueryResponse["Cache invalidation POST"] n1["{ @@ -236,14 +235,14 @@ flowchart RL end subgraph PriceQueryFragment["Price Query Fragment (e.g. TTL 2200)"] - n2["` ̶{̶ + n2[" ̶{̶   " ̶p̶r̶i̶c̶e̶": ̶{̶     " ̶i̶d̶": ̶1̶0̶1̶,     " ̶p̶r̶o̶d̶u̶c̶t̶_̶i̶d̶": ̶1̶2̶,     " ̶a̶m̶o̶u̶n̶t̶": ̶1̶5̶0̶0̶,     "̶c̶u̶r̶r̶e̶n̶c̶y̶_̶c̶o̶d̶e̶": " ̶U̶S̶D̶"    ̶}̶ - ̶}̶`"] + ̶}̶"] end Router From 4dc075113155126fe0980d46a09b402bf1ae3c4b Mon Sep 17 00:00:00 2001 From: Andrew Carlson <5479270+andrewicarlson@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:13:30 -0600 Subject: [PATCH 4/8] Added a title to the invalidation diagram --- docs/source/routing/performance/caching/entity.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/source/routing/performance/caching/entity.mdx b/docs/source/routing/performance/caching/entity.mdx index db9c5772e5..6bfe513b2a 100644 --- a/docs/source/routing/performance/caching/entity.mdx +++ b/docs/source/routing/performance/caching/entity.mdx @@ -83,8 +83,6 @@ flowchart RL }"] end - - subgraph Subgraphs["Subgraphs"] Purchases["Purchases"] Inventory["Inventory"] @@ -216,6 +214,10 @@ This entry contains an object with the `all` field to affect all subgraph reques ### Entity cache invalidation ```mermaid +--- +title: Invalidating an Entity Cache +--- + flowchart RL subgraph QueryResponse["Cache invalidation POST"] n1["{ From e6224cb88461006752a24c74df9f7261102e48b2 Mon Sep 17 00:00:00 2001 From: Andrew Carlson <5479270+andrewicarlson@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:52:06 -0600 Subject: [PATCH 5/8] Update docs/source/routing/performance/caching/entity.mdx Co-authored-by: Maria Elisabeth Schreiber --- docs/source/routing/performance/caching/entity.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/source/routing/performance/caching/entity.mdx b/docs/source/routing/performance/caching/entity.mdx index 6bfe513b2a..44b865a419 100644 --- a/docs/source/routing/performance/caching/entity.mdx +++ b/docs/source/routing/performance/caching/entity.mdx @@ -61,10 +61,9 @@ With entity caching enabled for this example, the router can: - Cache the cart per user, with a small amount of data. - Cache inventory data with a short TTL or not cache it at all. +For example, the diagram below shows how a price entity can be cached and then combined with purchase and inventory fragments to serve a `products` query. Because price data is subject to change less often than inventory data, it makes sense to cache it with a different TTL. + ```mermaid ---- -title: Entity Caching using the "Price" entity ---- flowchart RL subgraph QueryResponse["JSON Response"] n1["{ From 00bf83affa41d46c81aad0c6d281fa51ccb68872 Mon Sep 17 00:00:00 2001 From: Andrew Carlson <5479270+andrewicarlson@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:52:26 -0600 Subject: [PATCH 6/8] Update docs/source/routing/performance/caching/entity.mdx Co-authored-by: Maria Elisabeth Schreiber --- docs/source/routing/performance/caching/entity.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/source/routing/performance/caching/entity.mdx b/docs/source/routing/performance/caching/entity.mdx index 44b865a419..409acac085 100644 --- a/docs/source/routing/performance/caching/entity.mdx +++ b/docs/source/routing/performance/caching/entity.mdx @@ -212,10 +212,9 @@ This entry contains an object with the `all` field to affect all subgraph reques ### Entity cache invalidation +You can invalidate entity cache entries with a [specifically formatted request](#invalidation-request-format once you [configure your router](#configuration) appropriately. For example, if price data changes before a price entity's TTL expires, you can send an invalidation request. + ```mermaid ---- -title: Invalidating an Entity Cache ---- flowchart RL subgraph QueryResponse["Cache invalidation POST"] From 46ee5c76ac685d44c3a96da3e56f434bfd040d5f Mon Sep 17 00:00:00 2001 From: Andrew Carlson <5479270+andrewicarlson@users.noreply.github.com> Date: Thu, 14 Nov 2024 12:53:52 -0600 Subject: [PATCH 7/8] Update docs/source/routing/performance/caching/entity.mdx --- docs/source/routing/performance/caching/entity.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/routing/performance/caching/entity.mdx b/docs/source/routing/performance/caching/entity.mdx index 409acac085..76e9a616b1 100644 --- a/docs/source/routing/performance/caching/entity.mdx +++ b/docs/source/routing/performance/caching/entity.mdx @@ -248,7 +248,7 @@ flowchart RL Router Database[("   ")] - Router --> QueryResponse + QueryResponse --> Router Purchases --> Router Inventory --> Router Price --- Router From a22c838af48bf06c22a32878399d4cd7d37ac9f3 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Fri, 15 Nov 2024 10:43:04 +0100 Subject: [PATCH 8/8] Pass parameters explicitely in QueryPlannerRequest instead of context (#6208) --- apollo-router/src/error.rs | 14 +++ .../cost_calculator/static_cost.rs | 12 ++- .../src/query_planner/bridge_query_planner.rs | 47 +------- .../bridge_query_planner_pool.rs | 20 +++- .../query_planner/caching_query_planner.rs | 102 +++++------------- apollo-router/src/services/query_planner.rs | 26 +++-- .../src/services/supergraph/service.rs | 6 +- .../apollo_otel_traces__condition_else-2.snap | 2 +- .../apollo_otel_traces__condition_else.snap | 2 +- .../apollo_otel_traces__condition_if-2.snap | 2 +- .../apollo_otel_traces__condition_if.snap | 2 +- .../apollo_reports__condition_else-2.snap | 2 +- .../apollo_reports__condition_else.snap | 2 +- .../apollo_reports__condition_if-2.snap | 2 +- .../apollo_reports__condition_if.snap | 2 +- 15 files changed, 98 insertions(+), 145 deletions(-) diff --git a/apollo-router/src/error.rs b/apollo-router/src/error.rs index b6281a58d6..d78cd86728 100644 --- a/apollo-router/src/error.rs +++ b/apollo-router/src/error.rs @@ -1,4 +1,5 @@ //! Router errors. +use std::collections::HashMap; use std::sync::Arc; use apollo_compiler::validation::DiagnosticList; @@ -412,6 +413,19 @@ impl IntoGraphQLErrors for QueryPlannerError { } } +impl QueryPlannerError { + pub(crate) fn usage_reporting(&self) -> Option { + match self { + QueryPlannerError::PlanningErrors(pe) => Some(pe.usage_reporting.clone()), + QueryPlannerError::SpecError(e) => Some(UsageReporting { + stats_report_key: e.get_error_key().to_string(), + referenced_fields_by_type: HashMap::new(), + }), + _ => None, + } + } +} + #[derive(Clone, Debug, Error, Serialize, Deserialize)] /// Container for planner setup errors pub(crate) struct PlannerErrors(Arc>); diff --git a/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs b/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs index 98f3f275ed..3c0d973ebb 100644 --- a/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs +++ b/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs @@ -578,11 +578,13 @@ mod tests { use ahash::HashMapExt; use apollo_federation::query_plan::query_planner::QueryPlanner; use bytes::Bytes; + use router_bridge::planner::PlanOptions; use test_log::test; use tower::Service; use super::*; use crate::introspection::IntrospectionCache; + use crate::plugins::authorization::CacheKeyMetadata; use crate::query_planner::BridgeQueryPlanner; use crate::services::layers::query_analysis::ParsedDocument; use crate::services::QueryPlannerContent; @@ -681,10 +683,16 @@ mod tests { let ctx = Context::new(); ctx.extensions() - .with_lock(|mut lock| lock.insert::(query)); + .with_lock(|mut lock| lock.insert::(query.clone())); let planner_res = planner - .call(QueryPlannerRequest::new(query_str.to_string(), None, ctx)) + .call(QueryPlannerRequest::new( + query_str.to_string(), + None, + query, + CacheKeyMetadata::default(), + PlanOptions::default(), + )) .await .unwrap(); let query_plan = match planner_res.content.unwrap() { diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index f10e424bb3..e3cc52dcdd 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -43,7 +43,6 @@ use crate::metrics::meter_provider; use crate::plugins::authorization::AuthorizationPlugin; use crate::plugins::authorization::CacheKeyMetadata; use crate::plugins::authorization::UnauthorizedPaths; -use crate::plugins::progressive_override::LABELS_TO_OVERRIDE_KEY; use crate::plugins::telemetry::config::ApolloSignatureNormalizationAlgorithm; use crate::plugins::telemetry::config::Conf as TelemetryConfig; use crate::query_planner::convert::convert_root_query_plan_node; @@ -594,21 +593,14 @@ impl Service for BridgeQueryPlanner { let QueryPlannerRequest { query: original_query, operation_name, - context, + document, + metadata, + plan_options, } = req; - let metadata = context - .extensions() - .with_lock(|lock| lock.get::().cloned().unwrap_or_default()); let this = self.clone(); let fut = async move { - let mut doc = match context - .extensions() - .with_lock(|lock| lock.get::().cloned()) - { - None => return Err(QueryPlannerError::SpecError(SpecError::UnknownFileId)), - Some(d) => d, - }; + let mut doc = document; let api_schema = this.schema.api_schema(); match add_defer_labels(api_schema, &doc.ast) { @@ -635,19 +627,9 @@ impl Service for BridgeQueryPlanner { operation_name.as_deref(), Arc::new(QueryHash(hash)), )?; - context - .extensions() - .with_lock(|mut lock| lock.insert::(doc.clone())); } } - let plan_options = PlanOptions { - override_conditions: context - .get(LABELS_TO_OVERRIDE_KEY) - .unwrap_or_default() - .unwrap_or_default(), - }; - let res = this .get( QueryKey { @@ -664,27 +646,8 @@ impl Service for BridgeQueryPlanner { match res { Ok(query_planner_content) => Ok(QueryPlannerResponse::builder() .content(query_planner_content) - .context(context) .build()), - Err(e) => { - match &e { - QueryPlannerError::PlanningErrors(pe) => { - context.extensions().with_lock(|mut lock| { - lock.insert(Arc::new(pe.usage_reporting.clone())) - }); - } - QueryPlannerError::SpecError(e) => { - context.extensions().with_lock(|mut lock| { - lock.insert(Arc::new(UsageReporting { - stats_report_key: e.get_error_key().to_string(), - referenced_fields_by_type: HashMap::new(), - })) - }); - } - _ => (), - } - Err(e) - } + Err(e) => Err(e), } }; diff --git a/apollo-router/src/query_planner/bridge_query_planner_pool.rs b/apollo-router/src/query_planner/bridge_query_planner_pool.rs index 722a965efd..652bc997b9 100644 --- a/apollo-router/src/query_planner/bridge_query_planner_pool.rs +++ b/apollo-router/src/query_planner/bridge_query_planner_pool.rs @@ -300,9 +300,11 @@ impl tower::Service for BridgeQueryPlannerPool { mod tests { use opentelemetry_sdk::metrics::data::Gauge; + use router_bridge::planner::PlanOptions; use super::*; use crate::metrics::FutureMetricsExt; + use crate::plugins::authorization::CacheKeyMetadata; use crate::spec::Query; use crate::Context; @@ -326,11 +328,19 @@ mod tests { let doc = Query::parse_document(&query, None, &schema, &config).unwrap(); let context = Context::new(); - context.extensions().with_lock(|mut lock| lock.insert(doc)); - - pool.call(QueryPlannerRequest::new(query, None, context)) - .await - .unwrap(); + context + .extensions() + .with_lock(|mut lock| lock.insert(doc.clone())); + + pool.call(QueryPlannerRequest::new( + query, + None, + doc, + CacheKeyMetadata::default(), + PlanOptions::default(), + )) + .await + .unwrap(); let metrics = crate::metrics::collect_metrics(); let heap_used = metrics.find("apollo.router.v8.heap.used").unwrap(); diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index 688ce1c697..ba65ba52a6 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::hash::Hash; use std::hash::Hasher; -use std::ops::Deref; use std::sync::Arc; use std::task; @@ -36,7 +35,6 @@ use crate::plugins::authorization::CacheKeyMetadata; use crate::plugins::progressive_override::LABELS_TO_OVERRIDE_KEY; use crate::plugins::telemetry::utils::Timer; use crate::query_planner::fetch::SubgraphSchemas; -use crate::query_planner::labeler::add_defer_labels; use crate::query_planner::BridgeQueryPlannerPool; use crate::query_planner::QueryPlanResult; use crate::services::layers::persisted_queries::PersistedQueryLayer; @@ -49,7 +47,6 @@ use crate::services::QueryPlannerResponse; use crate::spec::Schema; use crate::spec::SpecError; use crate::Configuration; -use crate::Context; /// An [`IndexMap`] of available plugins. pub(crate) type Plugins = IndexMap>; @@ -274,7 +271,7 @@ where let mut count = 0usize; let mut reused = 0usize; for WarmUpCachingQueryKey { - mut query, + query, operation_name, hash, metadata, @@ -282,7 +279,6 @@ where config_mode: _, } in all_cache_keys { - let context = Context::new(); let doc = match query_analysis .parse_document(&query, operation_name.as_deref()) .await @@ -340,25 +336,12 @@ where } }; - let schema = self.schema.api_schema(); - if let Ok(modified_query) = add_defer_labels(schema, &doc.ast) { - query = modified_query.to_string(); - } - - context.extensions().with_lock(|mut lock| { - lock.insert::(doc); - lock.insert(caching_key.metadata) - }); - - let _ = context.insert( - LABELS_TO_OVERRIDE_KEY, - caching_key.plan_options.override_conditions.clone(), - ); - let request = QueryPlannerRequest { query, operation_name, - context: context.clone(), + document: doc, + metadata: caching_key.metadata, + plan_options: caching_key.plan_options, }; let res = match service.ready().await { @@ -429,16 +412,16 @@ where let qp = self.clone(); Box::pin(async move { let context = request.context.clone(); - qp.plan(request).await.inspect(|response| { + qp.plan(request).await.inspect(|_response| { if let Some(usage_reporting) = context .extensions() .with_lock(|lock| lock.get::>().cloned()) { - let _ = response.context.insert( + let _ = context.insert( APOLLO_OPERATION_ID, stats_report_key_hash(usage_reporting.stats_report_key.as_str()), ); - let _ = response.context.insert( + let _ = context.insert( "apollo_operation_signature", usage_reporting.stats_report_key.clone(), ); @@ -516,20 +499,17 @@ where .await; if entry.is_first() { let query_planner::CachingRequest { - mut query, + query, operation_name, context, } = request; - let schema = self.schema.api_schema(); - if let Ok(modified_query) = add_defer_labels(schema, &doc.ast) { - query = modified_query.to_string(); - } - let request = QueryPlannerRequest::builder() .query(query) .and_operation_name(operation_name) - .context(context) + .document(doc) + .metadata(caching_key.metadata) + .plan_options(caching_key.plan_options) .build(); // some clients might timeout and cancel the request before query planning is finished, @@ -541,11 +521,7 @@ where let res = self.delegate.ready().await?.call(request).await; match res { - Ok(QueryPlannerResponse { - content, - context, - errors, - }) => { + Ok(QueryPlannerResponse { content, errors }) => { if let Some(content) = content.clone() { let can_cache = match &content { // Already cached in an introspection-specific, small-size, @@ -569,11 +545,7 @@ where lock.insert::>(plan.usage_reporting.clone()) }); } - Ok(QueryPlannerResponse { - content, - context, - errors, - }) + Ok(QueryPlannerResponse { content, errors }) } Err(error) => { let e = Arc::new(error); @@ -581,6 +553,11 @@ where tokio::spawn(async move { entry.insert(Err(err)).await; }); + if let Some(usage_reporting) = e.usage_reporting() { + context.extensions().with_lock(|mut lock| { + lock.insert::>(Arc::new(usage_reporting)); + }); + } Err(CacheResolverError::RetrievalError(e)) } } @@ -607,29 +584,13 @@ where }); } - Ok(QueryPlannerResponse::builder() - .content(content) - .context(context) - .build()) + Ok(QueryPlannerResponse::builder().content(content).build()) } Err(error) => { - match error.deref() { - QueryPlannerError::PlanningErrors(pe) => { - request.context.extensions().with_lock(|mut lock| { - lock.insert::>(Arc::new( - pe.usage_reporting.clone(), - )) - }); - } - QueryPlannerError::SpecError(e) => { - request.context.extensions().with_lock(|mut lock| { - lock.insert::>(Arc::new(UsageReporting { - stats_report_key: e.get_error_key().to_string(), - referenced_fields_by_type: HashMap::new(), - })) - }); - } - _ => {} + if let Some(usage_reporting) = error.usage_reporting() { + context.extensions().with_lock(|mut lock| { + lock.insert::>(Arc::new(usage_reporting)); + }); } Err(CacheResolverError::RetrievalError(error)) @@ -750,6 +711,7 @@ mod tests { use crate::spec::Query; use crate::spec::Schema; use crate::Configuration; + use crate::Context; mock! { #[derive(Debug)] @@ -892,10 +854,7 @@ mod tests { plan: Arc::new(query_plan), }; - Ok(QueryPlannerResponse::builder() - .content(qp_content) - .context(Context::new()) - .build()) + Ok(QueryPlannerResponse::builder().content(qp_content).build()) }); planner }); @@ -929,15 +888,15 @@ mod tests { .with_lock(|mut lock| lock.insert::(doc)); for _ in 0..5 { - assert!(planner + let _ = planner .call(query_planner::CachingRequest::new( "query Me { me { username } }".to_string(), Some("".into()), context.clone(), )) .await - .unwrap() - .context + .unwrap(); + assert!(context .extensions() .with_lock(|lock| lock.contains_key::>())); } @@ -970,10 +929,7 @@ mod tests { ), }; - Ok(QueryPlannerResponse::builder() - .content(qp_content) - .context(Context::new()) - .build()) + Ok(QueryPlannerResponse::builder().content(qp_content).build()) }); planner }); diff --git a/apollo-router/src/services/query_planner.rs b/apollo-router/src/services/query_planner.rs index 494bb7e2c7..d23a0e2ace 100644 --- a/apollo-router/src/services/query_planner.rs +++ b/apollo-router/src/services/query_planner.rs @@ -4,10 +4,12 @@ use std::sync::Arc; use async_trait::async_trait; use derivative::Derivative; +use router_bridge::planner::PlanOptions; use serde::Deserialize; use serde::Serialize; use static_assertions::assert_impl_all; +use super::layers::query_analysis::ParsedDocument; use crate::error::QueryPlannerError; use crate::graphql; use crate::query_planner::QueryPlan; @@ -20,7 +22,9 @@ assert_impl_all!(Request: Send); pub(crate) struct Request { pub(crate) query: String, pub(crate) operation_name: Option, - pub(crate) context: Context, + pub(crate) document: ParsedDocument, + pub(crate) metadata: crate::plugins::authorization::CacheKeyMetadata, + pub(crate) plan_options: PlanOptions, } #[buildstructor::buildstructor] @@ -29,11 +33,19 @@ impl Request { /// /// Required parameters are required in non-testing code to create a QueryPlannerRequest. #[builder] - pub(crate) fn new(query: String, operation_name: Option, context: Context) -> Request { + pub(crate) fn new( + query: String, + operation_name: Option, + document: ParsedDocument, + metadata: crate::plugins::authorization::CacheKeyMetadata, + plan_options: PlanOptions, + ) -> Request { Self { query, operation_name, - context, + document, + metadata, + plan_options, } } } @@ -72,7 +84,6 @@ pub(crate) struct Response { /// Optional in case of error pub(crate) content: Option, pub(crate) errors: Vec, - pub(crate) context: Context, } /// Query, QueryPlan and Introspection data. @@ -92,14 +103,9 @@ impl Response { #[builder] pub(crate) fn new( content: Option, - context: Context, errors: Vec, ) -> Response { - Self { - content, - context, - errors, - } + Self { content, errors } } } diff --git a/apollo-router/src/services/supergraph/service.rs b/apollo-router/src/services/supergraph/service.rs index a217df0bd1..f87c81727f 100644 --- a/apollo-router/src/services/supergraph/service.rs +++ b/apollo-router/src/services/supergraph/service.rs @@ -171,11 +171,7 @@ async fn service_call( let body = req.supergraph_request.body(); let variables = body.variables.clone(); - let QueryPlannerResponse { - content, - context, - errors, - } = match plan_query( + let QueryPlannerResponse { content, errors } = match plan_query( planning, body.operation_name.clone(), context.clone(), diff --git a/apollo-router/tests/snapshots/apollo_otel_traces__condition_else-2.snap b/apollo-router/tests/snapshots/apollo_otel_traces__condition_else-2.snap index 853672e8d0..602929d475 100644 --- a/apollo-router/tests/snapshots/apollo_otel_traces__condition_else-2.snap +++ b/apollo-router/tests/snapshots/apollo_otel_traces__condition_else-2.snap @@ -271,7 +271,7 @@ resourceSpans: stringValue: "[redacted]" - key: apollo_private.operation_signature value: - stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}" + stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" - key: apollo_private.query.aliases value: intValue: 0 diff --git a/apollo-router/tests/snapshots/apollo_otel_traces__condition_else.snap b/apollo-router/tests/snapshots/apollo_otel_traces__condition_else.snap index 853672e8d0..602929d475 100644 --- a/apollo-router/tests/snapshots/apollo_otel_traces__condition_else.snap +++ b/apollo-router/tests/snapshots/apollo_otel_traces__condition_else.snap @@ -271,7 +271,7 @@ resourceSpans: stringValue: "[redacted]" - key: apollo_private.operation_signature value: - stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}" + stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" - key: apollo_private.query.aliases value: intValue: 0 diff --git a/apollo-router/tests/snapshots/apollo_otel_traces__condition_if-2.snap b/apollo-router/tests/snapshots/apollo_otel_traces__condition_if-2.snap index 1b4bcb3cf1..69ea7edf5b 100644 --- a/apollo-router/tests/snapshots/apollo_otel_traces__condition_if-2.snap +++ b/apollo-router/tests/snapshots/apollo_otel_traces__condition_if-2.snap @@ -271,7 +271,7 @@ resourceSpans: stringValue: "[redacted]" - key: apollo_private.operation_signature value: - stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}" + stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" - key: apollo_private.query.aliases value: intValue: 0 diff --git a/apollo-router/tests/snapshots/apollo_otel_traces__condition_if.snap b/apollo-router/tests/snapshots/apollo_otel_traces__condition_if.snap index 1b4bcb3cf1..69ea7edf5b 100644 --- a/apollo-router/tests/snapshots/apollo_otel_traces__condition_if.snap +++ b/apollo-router/tests/snapshots/apollo_otel_traces__condition_if.snap @@ -271,7 +271,7 @@ resourceSpans: stringValue: "[redacted]" - key: apollo_private.operation_signature value: - stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}" + stringValue: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" - key: apollo_private.query.aliases value: intValue: 0 diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap b/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap index cae3641fd5..8fd3f3243e 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap @@ -11,7 +11,7 @@ header: uname: "[uname]" executable_schema_id: "[executable_schema_id]" traces_per_query: - "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}": + "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}": trace: - start_time: seconds: "[seconds]" diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_else.snap b/apollo-router/tests/snapshots/apollo_reports__condition_else.snap index cae3641fd5..8fd3f3243e 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_else.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_else.snap @@ -11,7 +11,7 @@ header: uname: "[uname]" executable_schema_id: "[executable_schema_id]" traces_per_query: - "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}": + "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}": trace: - start_time: seconds: "[seconds]" diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap b/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap index b9d955ee9c..282dbbb14d 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap @@ -11,7 +11,7 @@ header: uname: "[uname]" executable_schema_id: "[executable_schema_id]" traces_per_query: - "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}": + "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}": trace: - start_time: seconds: "[seconds]" diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_if.snap b/apollo-router/tests/snapshots/apollo_reports__condition_if.snap index b9d955ee9c..282dbbb14d 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_if.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_if.snap @@ -11,7 +11,7 @@ header: uname: "[uname]" executable_schema_id: "[executable_schema_id]" traces_per_query: - "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if,label:\"\"){reviews{author{name}}reviews{author{name}}}}}": + "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}": trace: - start_time: seconds: "[seconds]"