From be405744c81dbf1fe7732acdc31055c1ffb46c11 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 20 Jan 2025 14:06:45 +0100 Subject: [PATCH 01/38] Avoid re-computing implementers_map in QueryHashVisitor (#6569) --- apollo-router/src/axum_factory/tests.rs | 9 ++++- apollo-router/src/plugin/mod.rs | 9 +++-- .../cost_calculator/static_cost.rs | 2 +- .../src/plugins/include_subgraph_errors.rs | 8 ++++- apollo-router/src/plugins/test.rs | 7 +++- .../src/plugins/traffic_shaping/mod.rs | 8 ++++- .../src/query_planner/bridge_query_planner.rs | 36 +++++++++++++------ .../bridge_query_planner_pool.rs | 9 ++--- .../query_planner/caching_query_planner.rs | 10 ++---- apollo-router/src/query_planner/execution.rs | 6 ++-- apollo-router/src/query_planner/fetch.rs | 19 ++++++---- apollo-router/src/query_planner/tests.rs | 10 ++++-- apollo-router/src/router_factory.rs | 10 +++++- .../src/services/execution/service.rs | 7 ++-- .../src/services/supergraph/service.rs | 9 ++++- apollo-router/src/spec/query.rs | 12 ++++--- apollo-router/src/spec/query/change.rs | 33 +++++++++++------ 17 files changed, 138 insertions(+), 66 deletions(-) diff --git a/apollo-router/src/axum_factory/tests.rs b/apollo-router/src/axum_factory/tests.rs index efcf7e3ab3..cabe1d5742 100644 --- a/apollo-router/src/axum_factory/tests.rs +++ b/apollo-router/src/axum_factory/tests.rs @@ -2278,7 +2278,14 @@ async fn test_supergraph_timeout() { // we do the entire supergraph rebuilding instead of using `from_supergraph_mock_callback_and_configuration` // because we need the plugins to apply on the supergraph - let mut plugins = create_plugins(&conf, &schema, planner.subgraph_schemas(), None, None) + let subgraph_schemas = Arc::new( + planner + .subgraph_schemas() + .iter() + .map(|(k, v)| (k.clone(), v.schema.clone())) + .collect(), + ); + let mut plugins = create_plugins(&conf, &schema, subgraph_schemas, None, None) .await .unwrap(); diff --git a/apollo-router/src/plugin/mod.rs b/apollo-router/src/plugin/mod.rs index 9479e7f91a..f8750892c9 100644 --- a/apollo-router/src/plugin/mod.rs +++ b/apollo-router/src/plugin/mod.rs @@ -45,7 +45,6 @@ use tower::ServiceBuilder; use crate::graphql; use crate::layers::ServiceBuilderExt; use crate::notification::Notify; -use crate::query_planner::fetch::SubgraphSchemas; use crate::router_factory::Endpoint; use crate::services::execution; use crate::services::router; @@ -75,7 +74,7 @@ pub struct PluginInit { pub(crate) supergraph_schema: Arc>, /// The parsed subgraph schemas from the query planner, keyed by subgraph name - pub(crate) subgraph_schemas: Arc, + pub(crate) subgraph_schemas: Arc>>>, /// Launch ID pub(crate) launch_id: Option>, @@ -176,7 +175,7 @@ where supergraph_sdl: Arc, supergraph_schema_id: Arc, supergraph_schema: Arc>, - subgraph_schemas: Option>, + subgraph_schemas: Option>>>>, launch_id: Option>>, notify: Notify, ) -> Self { @@ -201,7 +200,7 @@ where supergraph_sdl: Arc, supergraph_schema_id: Arc, supergraph_schema: Arc>, - subgraph_schemas: Option>, + subgraph_schemas: Option>>>>, launch_id: Option>, notify: Notify, ) -> Result { @@ -224,7 +223,7 @@ where supergraph_sdl: Option>, supergraph_schema_id: Option>, supergraph_schema: Option>>, - subgraph_schemas: Option>, + subgraph_schemas: Option>>>>, launch_id: Option>, notify: Option>, ) -> Self { 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 ca7217ba7f..42c5865557 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 @@ -755,7 +755,7 @@ mod tests { let mut demand_controlled_subgraph_schemas = HashMap::new(); for (subgraph_name, subgraph_schema) in planner.subgraph_schemas().iter() { let demand_controlled_subgraph_schema = - DemandControlledSchema::new(subgraph_schema.clone()).unwrap(); + DemandControlledSchema::new(subgraph_schema.schema.clone()).unwrap(); demand_controlled_subgraph_schemas .insert(subgraph_name.to_string(), demand_controlled_subgraph_schema); } diff --git a/apollo-router/src/plugins/include_subgraph_errors.rs b/apollo-router/src/plugins/include_subgraph_errors.rs index 5641d0a506..371ebf3f1b 100644 --- a/apollo-router/src/plugins/include_subgraph_errors.rs +++ b/apollo-router/src/plugins/include_subgraph_errors.rs @@ -220,7 +220,13 @@ mod test { .await .unwrap(); let schema = planner.schema(); - let subgraph_schemas = planner.subgraph_schemas(); + let subgraph_schemas = Arc::new( + planner + .subgraph_schemas() + .iter() + .map(|(k, v)| (k.clone(), v.schema.clone())) + .collect(), + ); let builder = PluggableSupergraphServiceBuilder::new(planner); diff --git a/apollo-router/src/plugins/test.rs b/apollo-router/src/plugins/test.rs index 8535c9f5f1..31c9834c7f 100644 --- a/apollo-router/src/plugins/test.rs +++ b/apollo-router/src/plugins/test.rs @@ -120,7 +120,12 @@ impl> + 'static> PluginTestHarness { .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into()) .supergraph_sdl(supergraph_sdl) .supergraph_schema(Arc::new(parsed_schema)) - .subgraph_schemas(subgraph_schemas) + .subgraph_schemas(Arc::new( + subgraph_schemas + .iter() + .map(|(k, v)| (k.clone(), v.schema.clone())) + .collect(), + )) .notify(Notify::default()) .build(); diff --git a/apollo-router/src/plugins/traffic_shaping/mod.rs b/apollo-router/src/plugins/traffic_shaping/mod.rs index 935a670164..f3f300108c 100644 --- a/apollo-router/src/plugins/traffic_shaping/mod.rs +++ b/apollo-router/src/plugins/traffic_shaping/mod.rs @@ -594,7 +594,13 @@ mod test { ) .await .unwrap(); - let subgraph_schemas = planner.subgraph_schemas(); + let subgraph_schemas = Arc::new( + planner + .subgraph_schemas() + .iter() + .map(|(k, v)| (k.clone(), v.schema.clone())) + .collect(), + ); let mut builder = PluggableSupergraphServiceBuilder::new(planner).with_configuration(config.clone()); diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index 10edd392ae..4437d35772 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -1,13 +1,11 @@ //! Calls out to nodejs query planner -use std::collections::HashMap; use std::fmt::Debug; use std::ops::ControlFlow; use std::sync::Arc; use std::time::Instant; use apollo_compiler::ast; -use apollo_compiler::validation::Valid; use apollo_compiler::Name; use apollo_federation::error::FederationError; use apollo_federation::error::SingleFederationError; @@ -49,6 +47,8 @@ use crate::plugins::telemetry::config::Conf as TelemetryConfig; use crate::query_planner::convert::convert_root_query_plan_node; use crate::query_planner::dual_query_planner::BothModeComparisonJob; use crate::query_planner::fetch::QueryHash; +use crate::query_planner::fetch::SubgraphSchema; +use crate::query_planner::fetch::SubgraphSchemas; use crate::query_planner::labeler::add_defer_labels; use crate::services::layers::query_analysis::ParsedDocument; use crate::services::layers::query_analysis::ParsedDocumentInner; @@ -74,7 +74,7 @@ const INTERNAL_INIT_ERROR: &str = "internal"; pub(crate) struct BridgeQueryPlanner { planner: PlannerMode, schema: Arc, - subgraph_schemas: Arc>>>, + subgraph_schemas: Arc, configuration: Arc, enable_authorization_directives: bool, _federation_instrument: ObservableGauge, @@ -360,9 +360,7 @@ impl PlannerMode { } } - async fn subgraphs( - &self, - ) -> Result>>, ServiceBuildError> { + async fn subgraphs(&self) -> Result { let js = match self { PlannerMode::Js(js) => js, PlannerMode::Both { js, .. } => js, @@ -370,7 +368,15 @@ impl PlannerMode { return Ok(rust .subgraph_schemas() .iter() - .map(|(name, schema)| (name.to_string(), Arc::new(schema.schema().clone()))) + .map(|(name, schema)| { + ( + name.to_string(), + SubgraphSchema { + implementers_map: schema.schema().implementers_map(), + schema: Arc::new(schema.schema().clone()), + }, + ) + }) .collect()) } }; @@ -380,7 +386,13 @@ impl PlannerMode { .map(|(name, schema_str)| { let schema = apollo_compiler::Schema::parse_and_validate(schema_str, "") .map_err(|errors| SchemaError::Validate(errors.into()))?; - Ok((name, Arc::new(schema))) + Ok(( + name, + SubgraphSchema { + implementers_map: schema.implementers_map(), + schema: Arc::new(schema), + }, + )) }) .collect() } @@ -430,9 +442,7 @@ impl BridgeQueryPlanner { self.schema.clone() } - pub(crate) fn subgraph_schemas( - &self, - ) -> Arc>>> { + pub(crate) fn subgraph_schemas(&self) -> Arc { self.subgraph_schemas.clone() } @@ -619,6 +629,7 @@ impl Service for BridgeQueryPlanner { let hash = QueryHashVisitor::hash_query( this.schema.supergraph_schema(), &this.schema.raw_sdl, + &this.schema.implementers_map, &executable_document, operation_name.as_deref(), ) @@ -738,6 +749,7 @@ impl BridgeQueryPlanner { let hash = QueryHashVisitor::hash_query( self.schema.supergraph_schema(), &self.schema.raw_sdl, + &self.schema.implementers_map, &executable_document, key.operation_name.as_deref(), ) @@ -832,6 +844,8 @@ pub(crate) fn metric_rust_qp_init(init_error_kind: Option<&'static str>) { #[cfg(test)] mod tests { + use std::collections::HashMap; + use serde_json::json; use test_log::test; use tower::Service; 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 5246b79901..624ba2c7ac 100644 --- a/apollo-router/src/query_planner/bridge_query_planner_pool.rs +++ b/apollo-router/src/query_planner/bridge_query_planner_pool.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use std::num::NonZeroUsize; use std::sync::atomic::AtomicU64; use std::sync::atomic::Ordering; @@ -7,7 +6,6 @@ use std::sync::Mutex; use std::task::Poll; use std::time::Instant; -use apollo_compiler::validation::Valid; use async_channel::bounded; use async_channel::Sender; use futures::future::BoxFuture; @@ -27,6 +25,7 @@ use crate::error::QueryPlannerError; use crate::error::ServiceBuildError; use crate::introspection::IntrospectionCache; use crate::metrics::meter_provider; +use crate::query_planner::fetch::SubgraphSchemas; use crate::query_planner::PlannerMode; use crate::services::QueryPlannerRequest; use crate::services::QueryPlannerResponse; @@ -40,7 +39,7 @@ pub(crate) struct BridgeQueryPlannerPool { js_planners: Vec>>, pool_mode: PoolMode, schema: Arc, - subgraph_schemas: Arc>>>, + subgraph_schemas: Arc, compute_jobs_queue_size_gauge: Arc>>>, v8_heap_used: Arc, v8_heap_used_gauge: Arc>>>, @@ -248,9 +247,7 @@ impl BridgeQueryPlannerPool { self.schema.clone() } - pub(crate) fn subgraph_schemas( - &self, - ) -> Arc>>> { + pub(crate) fn subgraph_schemas(&self) -> Arc { self.subgraph_schemas.clone() } diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index 7b1f8c5279..a41db7cff0 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -1,10 +1,8 @@ -use std::collections::HashMap; use std::hash::Hash; use std::hash::Hasher; use std::sync::Arc; use std::task; -use apollo_compiler::validation::Valid; use futures::future::BoxFuture; use indexmap::IndexMap; use query_planner::QueryPlannerPlugin; @@ -72,7 +70,7 @@ pub(crate) struct CachingQueryPlanner { >, delegate: T, schema: Arc, - subgraph_schemas: Arc>>>, + subgraph_schemas: Arc, plugins: Arc, enable_authorization_directives: bool, config_mode_hash: Arc, @@ -105,7 +103,7 @@ where pub(crate) async fn new( delegate: T, schema: Arc, - subgraph_schemas: Arc>>>, + subgraph_schemas: Arc, configuration: &Configuration, plugins: Plugins, ) -> Result, BoxError> { @@ -382,9 +380,7 @@ impl CachingQueryPlanner { self.delegate.js_planners() } - pub(crate) fn subgraph_schemas( - &self, - ) -> Arc>>> { + pub(crate) fn subgraph_schemas(&self) -> Arc { self.delegate.subgraph_schemas() } diff --git a/apollo-router/src/query_planner/execution.rs b/apollo-router/src/query_planner/execution.rs index 9a5b647350..96d4be71a0 100644 --- a/apollo-router/src/query_planner/execution.rs +++ b/apollo-router/src/query_planner/execution.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use std::sync::Arc; -use apollo_compiler::validation::Valid; use futures::future::join_all; use futures::prelude::*; use tokio::sync::broadcast; @@ -23,6 +22,7 @@ use crate::json_ext::Path; use crate::json_ext::Value; use crate::json_ext::ValueExt; use crate::plugins::subscription::SubscriptionConfig; +use crate::query_planner::fetch::SubgraphSchemas; use crate::query_planner::FlattenNode; use crate::query_planner::Primary; use crate::query_planner::CONDITION_ELSE_SPAN_NAME; @@ -50,7 +50,7 @@ impl QueryPlan { service_factory: &'a Arc, supergraph_request: &'a Arc>, schema: &'a Arc, - subgraph_schemas: &'a Arc>>>, + subgraph_schemas: &'a Arc, sender: mpsc::Sender, subscription_handle: Option, subscription_config: &'a Option, @@ -106,7 +106,7 @@ pub(crate) struct ExecutionParameters<'a> { pub(crate) context: &'a Context, pub(crate) service_factory: &'a Arc, pub(crate) schema: &'a Arc, - pub(crate) subgraph_schemas: &'a Arc>>>, + pub(crate) subgraph_schemas: &'a Arc, pub(crate) supergraph_request: &'a Arc>, pub(crate) deferred_fetches: &'a HashMap)>>, pub(crate) query: &'a Arc, diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 3ec89c1e95..b8d64fa2c5 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -1,10 +1,11 @@ -use std::collections::HashMap; use std::fmt::Display; use std::sync::Arc; use apollo_compiler::ast; +use apollo_compiler::collections::HashMap; use apollo_compiler::validation::Valid; use apollo_compiler::ExecutableDocument; +use apollo_compiler::Name; use indexmap::IndexSet; use serde::Deserialize; use serde::Serialize; @@ -93,7 +94,12 @@ impl From for OperationKind { } } -pub(crate) type SubgraphSchemas = HashMap>>; +pub(crate) type SubgraphSchemas = HashMap; + +pub(crate) struct SubgraphSchema { + pub(crate) schema: Arc>, + pub(crate) implementers_map: HashMap, +} /// A fetch node. #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] @@ -406,7 +412,7 @@ impl FetchNode { if let Some(subgraph_schema) = parameters.subgraph_schemas.get(&service_name.to_string()) { - match build_operation_with_aliasing(operation, &ctx_arg, subgraph_schema) { + match build_operation_with_aliasing(operation, &ctx_arg, &subgraph_schema.schema) { Ok(op) => { alias_query_string = op.serialize().no_indent().to_string(); alias_query_string.as_str() @@ -680,7 +686,7 @@ impl FetchNode { subgraph_schemas: &SubgraphSchemas, ) -> Result<(), ValidationErrors> { let schema = &subgraph_schemas[self.service_name.as_ref()]; - self.operation.init_parsed(schema)?; + self.operation.init_parsed(&schema.schema)?; Ok(()) } @@ -690,11 +696,12 @@ impl FetchNode { supergraph_schema_hash: &str, ) -> Result<(), ValidationErrors> { let schema = &subgraph_schemas[self.service_name.as_ref()]; - let doc = self.operation.init_parsed(schema)?; + let doc = self.operation.init_parsed(&schema.schema)?; if let Ok(hash) = QueryHashVisitor::hash_query( - schema, + &schema.schema, supergraph_schema_hash, + &schema.implementers_map, doc, self.operation_name.as_deref(), ) { diff --git a/apollo-router/src/query_planner/tests.rs b/apollo-router/src/query_planner/tests.rs index 766ce9a715..2ab97e9d51 100644 --- a/apollo-router/src/query_planner/tests.rs +++ b/apollo-router/src/query_planner/tests.rs @@ -1838,8 +1838,14 @@ fn broken_plan_does_not_panic() { estimated_size: Default::default(), }; let subgraph_schema = apollo_compiler::Schema::parse_and_validate(subgraph_schema, "").unwrap(); - let mut subgraph_schemas = HashMap::new(); - subgraph_schemas.insert("X".to_owned(), Arc::new(subgraph_schema)); + let mut subgraph_schemas = HashMap::default(); + subgraph_schemas.insert( + "X".to_owned(), + query_planner::fetch::SubgraphSchema { + implementers_map: subgraph_schema.implementers_map(), + schema: Arc::new(subgraph_schema), + }, + ); let result = Arc::make_mut(&mut plan.root) .init_parsed_operations_and_hash_subqueries(&subgraph_schemas, ""); assert_eq!( diff --git a/apollo-router/src/router_factory.rs b/apollo-router/src/router_factory.rs index d34eae8b45..4c30b8fa66 100644 --- a/apollo-router/src/router_factory.rs +++ b/apollo-router/src/router_factory.rs @@ -337,11 +337,19 @@ impl YamlRouterFactory { let span = tracing::info_span!("plugins"); // Process the plugins. + let subgraph_schemas = Arc::new( + bridge_query_planner + .subgraph_schemas() + .iter() + .map(|(k, v)| (k.clone(), v.schema.clone())) + .collect(), + ); + let plugins: Arc = Arc::new( create_plugins( &configuration, &schema, - bridge_query_planner.subgraph_schemas(), + subgraph_schemas, initial_telemetry_plugin, extra_plugins, ) diff --git a/apollo-router/src/services/execution/service.rs b/apollo-router/src/services/execution/service.rs index 2869f1ade9..2712ad815c 100644 --- a/apollo-router/src/services/execution/service.rs +++ b/apollo-router/src/services/execution/service.rs @@ -1,6 +1,5 @@ //! Implements the Execution phase of the request lifecycle. -use std::collections::HashMap; use std::future::ready; use std::pin::Pin; use std::sync::Arc; @@ -9,7 +8,6 @@ use std::task::Poll; use std::time::SystemTime; use std::time::UNIX_EPOCH; -use apollo_compiler::validation::Valid; use futures::future::BoxFuture; use futures::stream::once; use futures::Stream; @@ -47,6 +45,7 @@ use crate::plugins::subscription::APOLLO_SUBSCRIPTION_PLUGIN; use crate::plugins::telemetry::apollo::Config as ApolloTelemetryConfig; use crate::plugins::telemetry::config::ApolloMetricsReferenceMode; use crate::plugins::telemetry::Telemetry; +use crate::query_planner::fetch::SubgraphSchemas; use crate::query_planner::subscription::SubscriptionHandle; use crate::services::execution; use crate::services::new_service::ServiceFactory; @@ -62,7 +61,7 @@ use crate::spec::Schema; #[derive(Clone)] pub(crate) struct ExecutionService { pub(crate) schema: Arc, - pub(crate) subgraph_schemas: Arc>>>, + pub(crate) subgraph_schemas: Arc, pub(crate) subgraph_service_factory: Arc, /// Subscription config if enabled subscription_config: Option, @@ -615,7 +614,7 @@ async fn consume_responses( #[derive(Clone)] pub(crate) struct ExecutionServiceFactory { pub(crate) schema: Arc, - pub(crate) subgraph_schemas: Arc>>>, + pub(crate) subgraph_schemas: Arc, pub(crate) plugins: Arc, pub(crate) subgraph_service_factory: Arc, } diff --git a/apollo-router/src/services/supergraph/service.rs b/apollo-router/src/services/supergraph/service.rs index b059c7aa07..b44c7d81b7 100644 --- a/apollo-router/src/services/supergraph/service.rs +++ b/apollo-router/src/services/supergraph/service.rs @@ -555,7 +555,14 @@ async fn subscription_task( // If the configuration was dropped in the meantime, we ignore this update and will // pick up the next one. if let Some(conf) = new_configuration.upgrade() { - let plugins = match create_plugins(&conf, &execution_service_factory.schema, execution_service_factory.subgraph_schemas.clone(), None, None).await { + let subgraph_schemas = Arc::new( + execution_service_factory + .subgraph_schemas + .iter() + .map(|(k, v)| (k.clone(), v.schema.clone())) + .collect(), + ); + let plugins = match create_plugins(&conf, &execution_service_factory.schema, subgraph_schemas, None, None).await { Ok(plugins) => Arc::new(plugins), Err(err) => { tracing::error!("cannot re-create plugins with the new configuration (closing existing subscription): {err:?}"); diff --git a/apollo-router/src/spec/query.rs b/apollo-router/src/spec/query.rs index 460f8cac3d..7a96bf51c8 100644 --- a/apollo-router/src/spec/query.rs +++ b/apollo-router/src/spec/query.rs @@ -269,6 +269,7 @@ impl Query { let hash = QueryHashVisitor::hash_query( schema.supergraph_schema(), &schema.raw_sdl, + &schema.implementers_map, &executable_document, operation_name, ) @@ -323,10 +324,13 @@ impl Query { let operation = get_operation(document, operation_name)?; let operation = Operation::from_hir(&operation, schema, &mut defer_stats, &fragments)?; - let mut visitor = - QueryHashVisitor::new(schema.supergraph_schema(), &schema.raw_sdl, document).map_err( - |e| SpecError::QueryHashing(format!("could not calculate the query hash: {e}")), - )?; + let mut visitor = QueryHashVisitor::new( + schema.supergraph_schema(), + &schema.raw_sdl, + &schema.implementers_map, + document, + ) + .map_err(|e| SpecError::QueryHashing(format!("could not calculate the query hash: {e}")))?; traverse::document(&mut visitor, document, operation_name).map_err(|e| { SpecError::QueryHashing(format!("could not calculate the query hash: {e}")) })?; diff --git a/apollo-router/src/spec/query/change.rs b/apollo-router/src/spec/query/change.rs index 73bda2881f..25481139ed 100644 --- a/apollo-router/src/spec/query/change.rs +++ b/apollo-router/src/spec/query/change.rs @@ -39,13 +39,13 @@ //! //! This prevents possible collision while hashing multiple things in a sequence. The //! `^` character cannot be present in GraphQL names, so this is a good separator. -use std::collections::HashMap; -use std::collections::HashSet; use std::hash::Hash; use std::hash::Hasher; use apollo_compiler::ast; use apollo_compiler::ast::FieldDefinition; +use apollo_compiler::collections::HashMap; +use apollo_compiler::collections::HashSet; use apollo_compiler::executable; use apollo_compiler::parser::Parser; use apollo_compiler::schema; @@ -79,6 +79,7 @@ pub(crate) struct QueryHashVisitor<'a> { // For now, introspection is still handled by the planner, so when an // introspection query is hashed, it should take the whole schema into account schema_str: &'a str, + implementers_map: &'a HashMap, hasher: Sha256, fragments: HashMap<&'a Name, &'a Node>, hashed_types: HashSet, @@ -95,15 +96,17 @@ impl<'a> QueryHashVisitor<'a> { pub(crate) fn new( schema: &'a schema::Schema, schema_str: &'a str, + implementers_map: &'a HashMap, executable: &'a executable::ExecutableDocument, ) -> Result { let mut visitor = Self { schema, schema_str, + implementers_map, hasher: Sha256::new(), fragments: executable.fragments.iter().collect(), - hashed_types: HashSet::new(), - hashed_field_definitions: HashSet::new(), + hashed_types: HashSet::default(), + hashed_field_definitions: HashSet::default(), seen_introspection: false, // should we just return an error if we do not find those directives? join_field_directive_name: Schema::directive_name( @@ -124,7 +127,7 @@ impl<'a> QueryHashVisitor<'a> { ">=0.1.0", CONTEXT_DIRECTIVE_NAME, ), - contexts: HashMap::new(), + contexts: HashMap::default(), }; visitor.hash_schema()?; @@ -147,10 +150,11 @@ impl<'a> QueryHashVisitor<'a> { pub(crate) fn hash_query( schema: &'a schema::Schema, schema_str: &'a str, + implementers_map: &'a HashMap, executable: &'a executable::ExecutableDocument, operation_name: Option<&str>, ) -> Result, BoxError> { - let mut visitor = QueryHashVisitor::new(schema, schema_str, executable)?; + let mut visitor = QueryHashVisitor::new(schema, schema_str, implementers_map, executable)?; traverse::document(&mut visitor, executable, operation_name)?; // hash the entire query string to prevent collisions executable.to_string().hash(&mut visitor); @@ -326,7 +330,7 @@ impl<'a> QueryHashVisitor<'a> { } "^IMPLEMENTED_INTERFACES_LIST_END".hash(self); - if let Some(implementers) = self.schema().implementers_map().get(&i.name) { + if let Some(implementers) = self.implementers_map.get(&i.name) { "^IMPLEMENTER_OBJECT_LIST".hash(self); for object in &implementers.objects { @@ -651,7 +655,7 @@ impl<'a> QueryHashVisitor<'a> { ) -> Result<(), BoxError> { "^INTERFACE_IMPL".hash(self); - if let Some(implementers) = self.schema.implementers_map().get(&intf.name) { + if let Some(implementers) = self.implementers_map.get(&intf.name) { "^IMPLEMENTER_LIST".hash(self); for object in &implementers.objects { self.hash_type_by_name(object)?; @@ -840,12 +844,17 @@ mod tests { .unwrap() .validate(&schema) .unwrap(); - let mut visitor = QueryHashVisitor::new(&schema, schema_str, &exec).unwrap(); + let implementers_map = schema.implementers_map(); + let mut visitor = + QueryHashVisitor::new(&schema, schema_str, &implementers_map, &exec).unwrap(); traverse::document(&mut visitor, &exec, None).unwrap(); ( hex::encode(visitor.finish()), - hex::encode(QueryHashVisitor::hash_query(&schema, schema_str, &exec, None).unwrap()), + hex::encode( + QueryHashVisitor::hash_query(&schema, schema_str, &implementers_map, &exec, None) + .unwrap(), + ), ) .into() } @@ -859,7 +868,9 @@ mod tests { .unwrap() .validate(&schema) .unwrap(); - let mut visitor = QueryHashVisitor::new(&schema, schema_str, &exec).unwrap(); + let implementers_map = schema.implementers_map(); + let mut visitor = + QueryHashVisitor::new(&schema, schema_str, &implementers_map, &exec).unwrap(); traverse::document(&mut visitor, &exec, None).unwrap(); hex::encode(visitor.finish()) From c3699e2e1cad61fbb6b7354d003e6d852eee5bb4 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Tue, 21 Jan 2025 12:04:35 +0200 Subject: [PATCH 02/38] WIP: Introduce QueryHash and SchemaHash types --- apollo-router/src/batching.rs | 2 +- apollo-router/src/plugin/mod.rs | 2 +- apollo-router/src/plugins/cache/entity.rs | 2 +- .../src/query_planner/bridge_query_planner.rs | 29 +++----- .../query_planner/caching_query_planner.rs | 3 +- apollo-router/src/query_planner/fetch.rs | 23 +----- apollo-router/src/query_planner/plan.rs | 2 +- apollo-router/src/router_factory.rs | 7 +- .../src/services/layers/query_analysis.rs | 4 +- apollo-router/src/services/subgraph.rs | 2 +- apollo-router/src/spec/mod.rs | 2 + apollo-router/src/spec/query.rs | 13 +--- apollo-router/src/spec/schema.rs | 73 +++++++++++++++++-- 13 files changed, 94 insertions(+), 70 deletions(-) diff --git a/apollo-router/src/batching.rs b/apollo-router/src/batching.rs index daa7884d99..f6cdab3e1e 100644 --- a/apollo-router/src/batching.rs +++ b/apollo-router/src/batching.rs @@ -23,7 +23,6 @@ use crate::error::FetchError; use crate::error::SubgraphBatchingError; use crate::graphql; use crate::plugins::telemetry::otel::span_ext::OpenTelemetrySpanExt; -use crate::query_planner::fetch::QueryHash; use crate::services::http::HttpClientServiceFactory; use crate::services::process_batches; use crate::services::router::body::get_body_bytes; @@ -31,6 +30,7 @@ use crate::services::router::body::RouterBody; use crate::services::subgraph::SubgraphRequestId; use crate::services::SubgraphRequest; use crate::services::SubgraphResponse; +use crate::spec::QueryHash; use crate::Context; /// A query that is part of a batch. diff --git a/apollo-router/src/plugin/mod.rs b/apollo-router/src/plugin/mod.rs index 9479e7f91a..9508ed3227 100644 --- a/apollo-router/src/plugin/mod.rs +++ b/apollo-router/src/plugin/mod.rs @@ -120,7 +120,7 @@ where BoxError::from(e.errors.to_string()) })?, )) - .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into()) + .supergraph_schema_id(crate::spec::SchemaHash(&supergraph_sdl).to_string()) .supergraph_sdl(supergraph_sdl) .notify(Notify::builder().build()) .build() diff --git a/apollo-router/src/plugins/cache/entity.rs b/apollo-router/src/plugins/cache/entity.rs index d50531dde2..37db0c2619 100644 --- a/apollo-router/src/plugins/cache/entity.rs +++ b/apollo-router/src/plugins/cache/entity.rs @@ -48,11 +48,11 @@ use crate::json_ext::PathElement; use crate::plugin::Plugin; use crate::plugin::PluginInit; use crate::plugins::authorization::CacheKeyMetadata; -use crate::query_planner::fetch::QueryHash; use crate::query_planner::OperationKind; use crate::services::subgraph; use crate::services::subgraph::SubgraphRequestId; use crate::services::supergraph; +use crate::spec::QueryHash; use crate::spec::TYPENAME; use crate::Context; use crate::Endpoint; diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index 10edd392ae..61cb7f2c03 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -48,7 +48,6 @@ use crate::plugins::telemetry::config::ApolloSignatureNormalizationAlgorithm; use crate::plugins::telemetry::config::Conf as TelemetryConfig; use crate::query_planner::convert::convert_root_query_plan_node; use crate::query_planner::dual_query_planner::BothModeComparisonJob; -use crate::query_planner::fetch::QueryHash; use crate::query_planner::labeler::add_defer_labels; use crate::services::layers::query_analysis::ParsedDocument; use crate::services::layers::query_analysis::ParsedDocumentInner; @@ -56,8 +55,8 @@ use crate::services::QueryPlannerContent; use crate::services::QueryPlannerRequest; use crate::services::QueryPlannerResponse; use crate::spec::operation_limits::OperationLimits; -use crate::spec::query::change::QueryHashVisitor; use crate::spec::Query; +use crate::spec::QueryHash; use crate::spec::Schema; use crate::spec::SpecError; use crate::Configuration; @@ -616,18 +615,16 @@ impl Service for BridgeQueryPlanner { .to_executable_validate(api_schema) // Assume transformation creates a valid document: ignore conversion errors .map_err(|e| SpecError::ValidationError(e.into()))?; - let hash = QueryHashVisitor::hash_query( - this.schema.supergraph_schema(), - &this.schema.raw_sdl, - &executable_document, + let hash = QueryHash::new( + &this.schema, + &modified_query.to_string(), operation_name.as_deref(), - ) - .map_err(|e| SpecError::QueryHashing(e.to_string()))?; + ); doc = ParsedDocumentInner::new( modified_query, Arc::new(executable_document), operation_name.as_deref(), - Arc::new(QueryHash(hash)), + Arc::new(hash), )?; } } @@ -731,22 +728,18 @@ impl BridgeQueryPlanner { }; if let Some((unauthorized_paths, new_doc)) = filter_res { - key.filtered_query = new_doc.to_string(); + let new_query = new_doc.to_string(); + let new_hash = QueryHash::new(&self.schema, &new_query, key.operation_name.as_deref()); + + key.filtered_query = new_query; let executable_document = new_doc .to_executable_validate(self.schema.api_schema()) .map_err(|e| SpecError::ValidationError(e.into()))?; - let hash = QueryHashVisitor::hash_query( - self.schema.supergraph_schema(), - &self.schema.raw_sdl, - &executable_document, - key.operation_name.as_deref(), - ) - .map_err(|e| SpecError::QueryHashing(e.to_string()))?; doc = ParsedDocumentInner::new( new_doc, Arc::new(executable_document), key.operation_name.as_deref(), - Arc::new(QueryHash(hash)), + Arc::new(new_hash), )?; selections.unauthorized.paths = unauthorized_paths; } diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index 7b1f8c5279..1471b49412 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -22,7 +22,6 @@ use tower::ServiceExt; use tower_service::Service; use tracing::Instrument; -use super::fetch::QueryHash; use crate::cache::estimate_size; use crate::cache::storage::InMemoryCache; use crate::cache::storage::ValueType; @@ -44,6 +43,7 @@ use crate::services::query_planner; use crate::services::QueryPlannerContent; use crate::services::QueryPlannerRequest; use crate::services::QueryPlannerResponse; +use crate::spec::QueryHash; use crate::spec::Schema; use crate::spec::SpecError; use crate::Configuration; @@ -630,7 +630,6 @@ fn stats_report_key_hash(stats_report_key: &str) -> String { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub(crate) struct CachingQueryKey { pub(crate) query: String, - pub(crate) schema_id: Arc, pub(crate) operation: Option, pub(crate) hash: Arc, pub(crate) metadata: CacheKeyMetadata, diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 3ec89c1e95..43da0305da 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -34,6 +34,7 @@ use crate::plugins::authorization::AuthorizationPlugin; use crate::plugins::authorization::CacheKeyMetadata; use crate::services::SubgraphRequest; use crate::spec::query::change::QueryHashVisitor; +use crate::spec::QueryHash; use crate::spec::Schema; /// GraphQL operation type. @@ -246,23 +247,6 @@ impl std::fmt::Display for SubgraphOperation { } } -#[derive(Clone, Default, Hash, PartialEq, Eq, Deserialize, Serialize)] -pub(crate) struct QueryHash(#[serde(with = "hex")] pub(crate) Vec); - -impl std::fmt::Debug for QueryHash { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("QueryHash") - .field(&hex::encode(&self.0)) - .finish() - } -} - -impl Display for QueryHash { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", hex::encode(&self.0)) - } -} - pub(crate) struct Variables { pub(crate) variables: Object, pub(crate) inverted_paths: Vec>, @@ -697,9 +681,8 @@ impl FetchNode { supergraph_schema_hash, doc, self.operation_name.as_deref(), - ) { - self.schema_aware_hash = Arc::new(QueryHash(hash)); - } + ) {} + self.schema_aware_hash = Arc::new(QueryHash::new(hash)); Ok(()) } diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index f0e5763358..000026627d 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -19,10 +19,10 @@ use crate::json_ext::Object; use crate::json_ext::Path; use crate::json_ext::Value; use crate::plugins::authorization::CacheKeyMetadata; -use crate::query_planner::fetch::QueryHash; use crate::query_planner::fetch::SubgraphSchemas; use crate::spec::operation_limits::OperationLimits; use crate::spec::Query; +use crate::spec::QueryHash; /// A planner key. /// diff --git a/apollo-router/src/router_factory.rs b/apollo-router/src/router_factory.rs index d34eae8b45..a31fbd4fba 100644 --- a/apollo-router/src/router_factory.rs +++ b/apollo-router/src/router_factory.rs @@ -553,7 +553,7 @@ pub(crate) async fn create_plugins( extra_plugins: Option)>>, ) -> Result { let supergraph_schema = Arc::new(schema.supergraph_schema().clone()); - let supergraph_schema_id = schema.schema_id.clone(); + let supergraph_schema_id = Arc::new(schema.schema_id.to_string()); let mut apollo_plugins_config = configuration.apollo_plugins.clone().plugins; let user_plugins_config = configuration.plugins.clone().plugins.unwrap_or_default(); let extra = extra_plugins.unwrap_or_default(); @@ -610,10 +610,7 @@ pub(crate) async fn create_plugins( // give it some. If any of the other mandatory plugins need special // treatment, then we'll have to perform it here. // This is *required* by the telemetry module or it will fail... - inject_schema_id( - Some(&Schema::schema_id(&schema.raw_sdl)), - &mut plugin_config, - ); + inject_schema_id(Some(&supergraph_schema_id), &mut plugin_config); } add_plugin!(name.to_string(), factory, plugin_config); } diff --git a/apollo-router/src/services/layers/query_analysis.rs b/apollo-router/src/services/layers/query_analysis.rs index 2e2fe77eff..0998b4e292 100644 --- a/apollo-router/src/services/layers/query_analysis.rs +++ b/apollo-router/src/services/layers/query_analysis.rs @@ -26,11 +26,11 @@ use crate::plugins::authorization::AuthorizationPlugin; use crate::plugins::telemetry::config::ApolloMetricsReferenceMode; use crate::plugins::telemetry::config::Conf as TelemetryConfig; use crate::plugins::telemetry::consts::QUERY_PARSING_SPAN_NAME; -use crate::query_planner::fetch::QueryHash; use crate::query_planner::OperationKind; use crate::services::SupergraphRequest; use crate::services::SupergraphResponse; use crate::spec::Query; +use crate::spec::QueryHash; use crate::spec::Schema; use crate::spec::SpecError; use crate::Configuration; @@ -323,7 +323,7 @@ impl Display for ParsedDocumentInner { impl Hash for ParsedDocumentInner { fn hash(&self, state: &mut H) { - self.hash.0.hash(state); + self.hash.hash(state); } } diff --git a/apollo-router/src/services/subgraph.rs b/apollo-router/src/services/subgraph.rs index 987eef24a0..5adaef39f8 100644 --- a/apollo-router/src/services/subgraph.rs +++ b/apollo-router/src/services/subgraph.rs @@ -31,7 +31,7 @@ use crate::json_ext::Path; use crate::plugins::authentication::APOLLO_AUTHENTICATION_JWT_CLAIMS; use crate::plugins::authorization::CacheKeyMetadata; use crate::query_planner::fetch::OperationKind; -use crate::query_planner::fetch::QueryHash; +use crate::spec::QueryHash; use crate::Context; pub type BoxService = tower::util::BoxService; diff --git a/apollo-router/src/spec/mod.rs b/apollo-router/src/spec/mod.rs index 786eb8a056..948751b8a8 100644 --- a/apollo-router/src/spec/mod.rs +++ b/apollo-router/src/spec/mod.rs @@ -14,7 +14,9 @@ pub(crate) use field_type::*; pub(crate) use fragments::*; pub(crate) use query::Query; pub(crate) use query::TYPENAME; +pub(crate) use schema::QueryHash; pub(crate) use schema::Schema; +pub(crate) use schema::SchemaHash; pub(crate) use selection::*; use serde::Deserialize; use serde::Serialize; diff --git a/apollo-router/src/spec/query.rs b/apollo-router/src/spec/query.rs index 460f8cac3d..e3c2782c96 100644 --- a/apollo-router/src/spec/query.rs +++ b/apollo-router/src/spec/query.rs @@ -32,7 +32,6 @@ use crate::json_ext::ResponsePathElement; use crate::json_ext::Value; use crate::plugins::authorization::UnauthorizedPaths; use crate::query_planner::fetch::OperationKind; -use crate::query_planner::fetch::QueryHash; use crate::services::layers::query_analysis::get_operation; use crate::services::layers::query_analysis::ParsedDocument; use crate::services::layers::query_analysis::ParsedDocumentInner; @@ -40,6 +39,7 @@ use crate::spec::schema::ApiSchema; use crate::spec::FieldType; use crate::spec::Fragments; use crate::spec::InvalidValue; +use crate::spec::QueryHash; use crate::spec::Schema; use crate::spec::Selection; use crate::spec::SpecError; @@ -266,19 +266,12 @@ impl Query { let recursion_limit = parser.recursion_reached(); tracing::trace!(?recursion_limit, "recursion limit data"); - let hash = QueryHashVisitor::hash_query( - schema.supergraph_schema(), - &schema.raw_sdl, - &executable_document, - operation_name, - ) - .map_err(|e| SpecError::QueryHashing(e.to_string()))?; - + let hash = schema.schema_id.operation_hash(query, operation_name); ParsedDocumentInner::new( ast, Arc::new(executable_document), operation_name, - Arc::new(QueryHash(hash)), + Arc::new(hash), ) } diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 8bfda05e64..fd561a7194 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -1,6 +1,7 @@ //! GraphQL schema. use std::collections::HashMap; +use std::fmt::Display; use std::str::FromStr; use std::sync::Arc; use std::time::Instant; @@ -14,6 +15,8 @@ use apollo_federation::Supergraph; use http::Uri; use semver::Version; use semver::VersionReq; +use serde::Deserialize; +use serde::Serialize; use sha2::Digest; use sha2::Sha256; @@ -30,7 +33,7 @@ pub(crate) struct Schema { subgraphs: HashMap, pub(crate) implementers_map: apollo_compiler::collections::HashMap, api_schema: ApiSchema, - pub(crate) schema_id: Arc, + pub(crate) schema_id: Arc, pub(crate) launch_id: Option>, } @@ -112,7 +115,7 @@ impl Schema { let implementers_map = definitions.implementers_map(); let supergraph = Supergraph::from_schema(definitions)?; - let schema_id = Arc::new(Schema::schema_id(&raw_sdl.sdl)); + let schema_id = Arc::new(SchemaHash::new(&raw_sdl.sdl)); let api_schema = supergraph .to_api_schema(ApiSchemaOptions { @@ -148,12 +151,6 @@ impl Schema { self.supergraph.schema.schema() } - pub(crate) fn schema_id(sdl: &str) -> String { - let mut hasher = Sha256::new(); - hasher.update(sdl.as_bytes()); - format!("{:x}", hasher.finalize()) - } - /// Extracts a string containing the entire [`Schema`]. pub(crate) fn as_string(&self) -> &Arc { &self.raw_sdl @@ -362,6 +359,66 @@ impl std::ops::Deref for ApiSchema { } } +#[derive(Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub(crate) struct SchemaHash(#[serde(with = "hex")] Vec); +impl SchemaHash { + pub fn new(sdl: &str) -> Self { + let mut hasher = Sha256::new(); + hasher.update(sdl); + Self(hasher.finalize().as_slice().into()) + } + + pub fn operation_hash(&self, query: &str, operation_name: Option<&str>) -> QueryHash { + let mut hasher = Sha256::new(); + hasher.update(self.0); + // byte separator between each part that is hashed + hasher.update(&[0xFF][..]); + hasher.update(query); + hasher.update(&[0xFF][..]); + hasher.update(operation_name.unwrap_or("-")); + QueryHash(hasher.finalize().as_slice().into()) + } +} + +impl std::fmt::Debug for SchemaHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("SchemaHash") + .field(&hex::encode(&self.0)) + .finish() + } +} + +impl Display for SchemaHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", hex::encode(&self.0)) + } +} + +// FIXME: rename to OperationHash since it include operation name +#[derive(Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub(crate) struct QueryHash(#[serde(with = "hex")] Vec); + +impl std::fmt::Debug for QueryHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("QueryHash") + .field(&hex::encode(&self.0)) + .finish() + } +} + +impl Display for QueryHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", hex::encode(&self.0)) + } +} + +#[cfg(test)] +impl Default for QueryHash { + fn default() -> Self { + Self(Default::default()) + } +} + #[cfg(test)] mod tests { use super::*; From 612db49d6004738c1dd22a840e4d68fa41f0b83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:00:51 +0100 Subject: [PATCH 03/38] Keep QueryHash::default but with scary comments --- apollo-router/src/services/subgraph.rs | 4 +++- apollo-router/src/spec/schema.rs | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apollo-router/src/services/subgraph.rs b/apollo-router/src/services/subgraph.rs index 5adaef39f8..fccf04fa34 100644 --- a/apollo-router/src/services/subgraph.rs +++ b/apollo-router/src/services/subgraph.rs @@ -102,7 +102,9 @@ impl Request { subgraph_name, subscription_stream, connection_closed_signal, - query_hash: Default::default(), + // XXX: This seems wrong and bad? + // We should figure out how this is used. + query_hash: QueryHash::default(), authorization: Default::default(), executable_document: None, id: SubgraphRequestId::new(), diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index fd561a7194..44c73fec33 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -412,7 +412,10 @@ impl Display for QueryHash { } } -#[cfg(test)] +// FIXME: It seems bad that you can create an empty hash easily and use it in security-critical +// places. This impl should be deleted outright and we should update usage sites. +// If the query hash is truly not required to contain data in those usage sites, we should use +// something like an Option instead. impl Default for QueryHash { fn default() -> Self { Self(Default::default()) From 7ac072b8386c4ae3e5c9f8ba10bacc88c40e0083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:15:43 +0100 Subject: [PATCH 04/38] Back to using Arc as the representation for schema ID --- apollo-router/src/plugin/mod.rs | 4 +- apollo-router/src/plugins/test.rs | 2 +- .../query_planner/caching_query_planner.rs | 4 +- apollo-router/src/spec/schema.rs | 53 +++++++++++++------ 4 files changed, 41 insertions(+), 22 deletions(-) diff --git a/apollo-router/src/plugin/mod.rs b/apollo-router/src/plugin/mod.rs index 9508ed3227..2a1f07236d 100644 --- a/apollo-router/src/plugin/mod.rs +++ b/apollo-router/src/plugin/mod.rs @@ -120,7 +120,7 @@ where BoxError::from(e.errors.to_string()) })?, )) - .supergraph_schema_id(crate::spec::SchemaHash(&supergraph_sdl).to_string()) + .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into_inner()) .supergraph_sdl(supergraph_sdl) .notify(Notify::builder().build()) .build() @@ -137,7 +137,7 @@ where PluginInit::fake_builder() .config(config) - .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into()) + .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into_inner()) .supergraph_sdl(supergraph_sdl) .supergraph_schema(supergraph_schema) .launch_id(Arc::new("launch_id".to_string())) diff --git a/apollo-router/src/plugins/test.rs b/apollo-router/src/plugins/test.rs index 8535c9f5f1..4d021ceb3b 100644 --- a/apollo-router/src/plugins/test.rs +++ b/apollo-router/src/plugins/test.rs @@ -117,7 +117,7 @@ impl> + 'static> PluginTestHarness { let plugin_init = PluginInit::builder() .config(config_for_plugin.clone()) - .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into()) + .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into_inner()) .supergraph_sdl(supergraph_sdl) .supergraph_schema(Arc::new(parsed_schema)) .subgraph_schemas(subgraph_schemas) diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index 1471b49412..0c98ff0e0f 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -295,7 +295,7 @@ where query: query.clone(), operation: operation_name.clone(), hash: doc.hash.clone(), - schema_id: Arc::clone(&self.schema.schema_id), + schema_id: self.schema.schema_id.clone(), metadata, plan_options, config_mode: self.config_mode_hash.clone(), @@ -488,7 +488,7 @@ where query: request.query.clone(), operation: request.operation_name.to_owned(), hash: doc.hash.clone(), - schema_id: Arc::clone(&self.schema.schema_id), + schema_id: self.schema.schema_id.clone(), metadata, plan_options, config_mode: self.config_mode_hash.clone(), diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 44c73fec33..74e25e0fad 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -33,7 +33,7 @@ pub(crate) struct Schema { subgraphs: HashMap, pub(crate) implementers_map: apollo_compiler::collections::HashMap, api_schema: ApiSchema, - pub(crate) schema_id: Arc, + pub(crate) schema_id: SchemaHash, pub(crate) launch_id: Option>, } @@ -115,7 +115,7 @@ impl Schema { let implementers_map = definitions.implementers_map(); let supergraph = Supergraph::from_schema(definitions)?; - let schema_id = Arc::new(SchemaHash::new(&raw_sdl.sdl)); + let schema_id = Schema::schema_id(&raw_sdl.sdl); let api_schema = supergraph .to_api_schema(ApiSchemaOptions { @@ -151,6 +151,11 @@ impl Schema { self.supergraph.schema.schema() } + /// Compute the Schema ID for an SDL string. + pub(crate) fn schema_id(sdl: &str) -> SchemaHash { + SchemaHash::new(sdl) + } + /// Extracts a string containing the entire [`Schema`]. pub(crate) fn as_string(&self) -> &Arc { &self.raw_sdl @@ -359,18 +364,40 @@ impl std::ops::Deref for ApiSchema { } } -#[derive(Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] -pub(crate) struct SchemaHash(#[serde(with = "hex")] Vec); +/// A schema ID is the sha256 hash of the schema text. +/// +/// That means that differences in whitespace and comments affect the hash, not only semantic +/// differences in the schema. +#[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] +pub(crate) struct SchemaHash( + /// The internal representation is a pointer to a string. + /// This is not ideal, it might be better eg. to just have a fixed-size byte array that can be + /// turned into a string as needed. + /// But `Arc` is used in the public plugin interface and other places, so this is + /// essentially a backwards compatibility decision. + Arc +); impl SchemaHash { - pub fn new(sdl: &str) -> Self { + pub(crate) fn new(sdl: &str) -> Self { let mut hasher = Sha256::new(); hasher.update(sdl); - Self(hasher.finalize().as_slice().into()) + let hash = format!("{:x}", hasher.finalize()); + Self(Arc::new(hash)) + } + + /// Return the underlying data. + pub(crate) fn into_inner(self) -> Arc { + self.0 + } + + /// Return the hash as a hexadecimal string slice. + pub(crate) fn as_str(&self) -> &str { + self.0.as_str() } - pub fn operation_hash(&self, query: &str, operation_name: Option<&str>) -> QueryHash { + pub(crate) fn operation_hash(&self, query: &str, operation_name: Option<&str>) -> QueryHash { let mut hasher = Sha256::new(); - hasher.update(self.0); + hasher.update(self.0.as_bytes()); // byte separator between each part that is hashed hasher.update(&[0xFF][..]); hasher.update(query); @@ -380,17 +407,9 @@ impl SchemaHash { } } -impl std::fmt::Debug for SchemaHash { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("SchemaHash") - .field(&hex::encode(&self.0)) - .finish() - } -} - impl Display for SchemaHash { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", hex::encode(&self.0)) + write!(f, "{}", self.0.as_str()) } } From 8d3c02e0eb2d6ff0016673292342d7698e138342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:16:32 +0100 Subject: [PATCH 05/38] Rename SchemaHash -> SchemaId --- apollo-router/src/spec/mod.rs | 2 +- apollo-router/src/spec/schema.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apollo-router/src/spec/mod.rs b/apollo-router/src/spec/mod.rs index 948751b8a8..ae682a9b42 100644 --- a/apollo-router/src/spec/mod.rs +++ b/apollo-router/src/spec/mod.rs @@ -16,7 +16,7 @@ pub(crate) use query::Query; pub(crate) use query::TYPENAME; pub(crate) use schema::QueryHash; pub(crate) use schema::Schema; -pub(crate) use schema::SchemaHash; +pub(crate) use schema::SchemaId; pub(crate) use selection::*; use serde::Deserialize; use serde::Serialize; diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 74e25e0fad..2bae2e97f6 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -33,7 +33,7 @@ pub(crate) struct Schema { subgraphs: HashMap, pub(crate) implementers_map: apollo_compiler::collections::HashMap, api_schema: ApiSchema, - pub(crate) schema_id: SchemaHash, + pub(crate) schema_id: SchemaId, pub(crate) launch_id: Option>, } @@ -152,8 +152,8 @@ impl Schema { } /// Compute the Schema ID for an SDL string. - pub(crate) fn schema_id(sdl: &str) -> SchemaHash { - SchemaHash::new(sdl) + pub(crate) fn schema_id(sdl: &str) -> SchemaId { + SchemaId::new(sdl) } /// Extracts a string containing the entire [`Schema`]. @@ -369,7 +369,7 @@ impl std::ops::Deref for ApiSchema { /// That means that differences in whitespace and comments affect the hash, not only semantic /// differences in the schema. #[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] -pub(crate) struct SchemaHash( +pub(crate) struct SchemaId( /// The internal representation is a pointer to a string. /// This is not ideal, it might be better eg. to just have a fixed-size byte array that can be /// turned into a string as needed. @@ -377,7 +377,7 @@ pub(crate) struct SchemaHash( /// essentially a backwards compatibility decision. Arc ); -impl SchemaHash { +impl SchemaId { pub(crate) fn new(sdl: &str) -> Self { let mut hasher = Sha256::new(); hasher.update(sdl); @@ -407,7 +407,7 @@ impl SchemaHash { } } -impl Display for SchemaHash { +impl Display for SchemaId { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0.as_str()) } From a600f7b6e9d95501195c6366f248a50199b62bd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:37:11 +0100 Subject: [PATCH 06/38] Introduce `ConfigModeHash` type The `QueryHash` type was reused here, but it's not hashing a query at all. --- .../query_planner/caching_query_planner.rs | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index 0c98ff0e0f..fabc209e8e 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -62,6 +62,22 @@ pub(crate) enum ConfigMode { Js(Arc), } +/// Hashed value of query planner configuration for use in cache keys. +#[derive(Clone, Hash, PartialEq, Eq)] +struct ConfigModeHash(Vec); + +impl std::fmt::Display for ConfigModeHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", hex::encode(&self.0)) + } +} + +impl std::fmt::Debug for ConfigModeHash { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("ConfigModeHash").field(&hex::encode(&self.0)).finish() + } +} + /// A query planner wrapper that caches results. /// /// The query planner performs LRU caching. @@ -75,7 +91,7 @@ pub(crate) struct CachingQueryPlanner { subgraph_schemas: Arc>>>, plugins: Arc, enable_authorization_directives: bool, - config_mode_hash: Arc, + config_mode_hash: Arc, } fn init_query_plan_from_redis( @@ -152,7 +168,7 @@ where .hash(&mut hasher); } }; - let config_mode_hash = Arc::new(QueryHash(hasher.finalize())); + let config_mode_hash = Arc::new(ConfigModeHash(hasher.finalize())); Ok(Self { cache, @@ -209,7 +225,7 @@ where hash, metadata, plan_options, - config_mode: _, + config_mode_hash: _, schema_id: _, }, _, @@ -219,7 +235,7 @@ where hash: Some(hash.clone()), metadata: metadata.clone(), plan_options: plan_options.clone(), - config_mode: self.config_mode_hash.clone(), + config_mode_hash: self.config_mode_hash.clone(), }, ) .take(count) @@ -264,7 +280,7 @@ where hash: None, metadata: CacheKeyMetadata::default(), plan_options: PlanOptions::default(), - config_mode: self.config_mode_hash.clone(), + config_mode_hash: self.config_mode_hash.clone(), }); } } @@ -280,7 +296,7 @@ where hash, metadata, plan_options, - config_mode: _, + config_mode_hash: _, } in all_cache_keys { let doc = match query_analysis @@ -298,7 +314,7 @@ where schema_id: self.schema.schema_id.clone(), metadata, plan_options, - config_mode: self.config_mode_hash.clone(), + config_mode_hash: self.config_mode_hash.clone(), }; if experimental_reuse_query_plans { @@ -491,7 +507,7 @@ where schema_id: self.schema.schema_id.clone(), metadata, plan_options, - config_mode: self.config_mode_hash.clone(), + config_mode_hash: self.config_mode_hash.clone(), }; let context = request.context.clone(); @@ -634,7 +650,7 @@ pub(crate) struct CachingQueryKey { pub(crate) hash: Arc, pub(crate) metadata: CacheKeyMetadata, pub(crate) plan_options: PlanOptions, - pub(crate) config_mode: Arc, + pub(crate) config_mode_hash: Arc, } const ROUTER_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -651,7 +667,7 @@ impl std::fmt::Display for CachingQueryKey { "^plan_options".hash(&mut hasher); self.plan_options.hash(&mut hasher); "^config_mode".hash(&mut hasher); - self.config_mode.hash(&mut hasher); + self.config_mode_hash.hash(&mut hasher); let metadata = hex::encode(hasher.finalize()); write!( @@ -669,7 +685,7 @@ pub(crate) struct WarmUpCachingQueryKey { pub(crate) hash: Option>, pub(crate) metadata: CacheKeyMetadata, pub(crate) plan_options: PlanOptions, - pub(crate) config_mode: Arc, + pub(crate) config_mode_hash: Arc, } struct StructHasher { From 43f001f540ac673036e720f0fb7f1f9573da8e51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:41:13 +0100 Subject: [PATCH 07/38] Update API usage --- apollo-router/src/plugin/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apollo-router/src/plugin/mod.rs b/apollo-router/src/plugin/mod.rs index 2a1f07236d..cceabde1df 100644 --- a/apollo-router/src/plugin/mod.rs +++ b/apollo-router/src/plugin/mod.rs @@ -96,7 +96,7 @@ where Schema::parse_and_validate(supergraph_sdl.to_string(), PathBuf::from("synthetic")) .expect("failed to parse supergraph schema"), )) - .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into()) + .supergraph_schema_id(crate::spec::Schema::schema_id(&supergraph_sdl).into_inner()) .supergraph_sdl(supergraph_sdl) .notify(Notify::builder().build()) .build() From 68a373815851350fcfa2510806e2090904698f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:41:26 +0100 Subject: [PATCH 08/38] Reintroduce schema_id field to CachingQueryKey This is just to keep it compiling right now, we can remove it at the end (it's probably right to do so) --- apollo-router/src/query_planner/caching_query_planner.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index fabc209e8e..0c19d0b45f 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -45,6 +45,7 @@ use crate::services::QueryPlannerRequest; use crate::services::QueryPlannerResponse; use crate::spec::QueryHash; use crate::spec::Schema; +use crate::spec::SchemaId; use crate::spec::SpecError; use crate::Configuration; @@ -648,6 +649,10 @@ pub(crate) struct CachingQueryKey { pub(crate) query: String, pub(crate) operation: Option, pub(crate) hash: Arc, + // XXX(@goto-bus-stop): It's probably correct to remove this, since having it here is + // misleading. The schema ID is *not* used in the Redis cache, but it's okay because the QueryHash + // is schema-aware. + pub(crate) schema_id: SchemaId, pub(crate) metadata: CacheKeyMetadata, pub(crate) plan_options: PlanOptions, pub(crate) config_mode_hash: Arc, From ee1b489af5ce7491b6f5141db1a130fdf8f04e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:47:04 +0100 Subject: [PATCH 09/38] Update two schema aware hash callsites (this may not be all) --- apollo-router/src/query_planner/bridge_query_planner.rs | 2 +- apollo-router/src/query_planner/fetch.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index 61cb7f2c03..d940ec132d 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -729,7 +729,7 @@ impl BridgeQueryPlanner { if let Some((unauthorized_paths, new_doc)) = filter_res { let new_query = new_doc.to_string(); - let new_hash = QueryHash::new(&self.schema, &new_query, key.operation_name.as_deref()); + let new_hash = self.schema.schema_id.operation_hash(&new_query, key.operation_name.as_deref()); key.filtered_query = new_query; let executable_document = new_doc diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 43da0305da..04f14590d3 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -682,7 +682,7 @@ impl FetchNode { doc, self.operation_name.as_deref(), ) {} - self.schema_aware_hash = Arc::new(QueryHash::new(hash)); + self.schema_aware_hash = Arc::new(todo!("Here we need either schema.operation_hash() or the advanced query-aware hash")); // QueryHash::new(hash)); Ok(()) } From d33e40dc5173eba3cf43e02bd4005afee2814b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 12:47:23 +0100 Subject: [PATCH 10/38] Document QueryHash --- apollo-router/src/spec/query.rs | 1 - apollo-router/src/spec/schema.rs | 46 ++++++++++++++++++++++++-------- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/apollo-router/src/spec/query.rs b/apollo-router/src/spec/query.rs index e3c2782c96..ef0e747593 100644 --- a/apollo-router/src/spec/query.rs +++ b/apollo-router/src/spec/query.rs @@ -39,7 +39,6 @@ use crate::spec::schema::ApiSchema; use crate::spec::FieldType; use crate::spec::Fragments; use crate::spec::InvalidValue; -use crate::spec::QueryHash; use crate::spec::Schema; use crate::spec::Selection; use crate::spec::SpecError; diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 2bae2e97f6..360888ea28 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -395,15 +395,11 @@ impl SchemaId { self.0.as_str() } - pub(crate) fn operation_hash(&self, query: &str, operation_name: Option<&str>) -> QueryHash { - let mut hasher = Sha256::new(); - hasher.update(self.0.as_bytes()); - // byte separator between each part that is hashed - hasher.update(&[0xFF][..]); - hasher.update(query); - hasher.update(&[0xFF][..]); - hasher.update(operation_name.unwrap_or("-")); - QueryHash(hasher.finalize().as_slice().into()) + /// Compute the hash for an executable document and operation name against this schema. + /// + /// See [QueryHash] for details of what's included. + pub(crate) fn operation_hash(&self, query_text: &str, operation_name: Option<&str>) -> QueryHash { + QueryHash::new(self, query_text, operation_name) } } @@ -413,9 +409,37 @@ impl Display for SchemaId { } } -// FIXME: rename to OperationHash since it include operation name +/// A query hash is a unique hash for an operation from an executable document against a particular +/// schema. +/// +/// For a document with two queries A and B, queries A and B will result in a different hash even +/// if the document text is identical. +/// If query A is then executed against two different versions of the schema, the hash will be +/// different again, depending on the [SchemaId]. +/// +/// A query hash can be obtained from a schema ID using [SchemaId::operation_hash]. +// FIXME: rename to OperationHash since it include operation name? #[derive(Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] -pub(crate) struct QueryHash(#[serde(with = "hex")] Vec); +pub(crate) struct QueryHash( + /// Unlike SchemaId, the query hash has no backwards compatibility motivations for the internal + /// type, as it's fully private. We could consider making this a fixed-size byte array rather + /// than a Vec, but it shouldn't make a huge difference. + #[serde(with = "hex")] Vec +); + +impl QueryHash { + /// This constructor is not public, see [SchemaId::operation_hash] instead. + fn new(schema_id: &SchemaId, query_text: &str, operation_name: Option<&str>) -> Self { + let mut hasher = Sha256::new(); + hasher.update(schema_id.as_str()); + // byte separator between each part that is hashed + hasher.update(&[0xFF][..]); + hasher.update(query_text); + hasher.update(&[0xFF][..]); + hasher.update(operation_name.unwrap_or("-")); + Self(hasher.finalize().as_slice().into()) + } +} impl std::fmt::Debug for QueryHash { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { From a0b9deaa6c555feb849a1a2950086ef482a325a2 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Tue, 21 Jan 2025 15:40:18 +0200 Subject: [PATCH 11/38] next step --- .../src/query_planner/bridge_query_planner.rs | 17 +++++------ apollo-router/src/query_planner/fetch.rs | 4 ++- apollo-router/src/query_planner/plan.rs | 1 + apollo-router/src/router_factory.rs | 28 +++++++++---------- apollo-router/src/spec/query.rs | 27 ++++++------------ apollo-router/src/spec/schema.rs | 11 ++++++-- 6 files changed, 43 insertions(+), 45 deletions(-) diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index d940ec132d..2ca7e91d81 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -56,7 +56,6 @@ use crate::services::QueryPlannerRequest; use crate::services::QueryPlannerResponse; use crate::spec::operation_limits::OperationLimits; use crate::spec::Query; -use crate::spec::QueryHash; use crate::spec::Schema; use crate::spec::SpecError; use crate::Configuration; @@ -452,7 +451,7 @@ impl BridgeQueryPlanner { )?; let (fragments, operation, defer_stats, schema_aware_hash) = - Query::extract_query_information(&self.schema, executable, operation_name)?; + Query::extract_query_information(&self.schema, &query, executable, operation_name)?; let subselections = crate::spec::query::subselections::collect_subselections( &self.configuration, @@ -615,11 +614,10 @@ impl Service for BridgeQueryPlanner { .to_executable_validate(api_schema) // Assume transformation creates a valid document: ignore conversion errors .map_err(|e| SpecError::ValidationError(e.into()))?; - let hash = QueryHash::new( - &this.schema, - &modified_query.to_string(), - operation_name.as_deref(), - ); + let hash = self + .schema + .schema_id + .operation_hash(&modified_query.to_string(), operation_name.as_deref()); doc = ParsedDocumentInner::new( modified_query, Arc::new(executable_document), @@ -729,7 +727,10 @@ impl BridgeQueryPlanner { if let Some((unauthorized_paths, new_doc)) = filter_res { let new_query = new_doc.to_string(); - let new_hash = self.schema.schema_id.operation_hash(&new_query, key.operation_name.as_deref()); + let new_hash = self + .schema + .schema_id + .operation_hash(&new_query, key.operation_name.as_deref()); key.filtered_query = new_query; let executable_document = new_doc diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 04f14590d3..3d2206042b 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -682,7 +682,9 @@ impl FetchNode { doc, self.operation_name.as_deref(), ) {} - self.schema_aware_hash = Arc::new(todo!("Here we need either schema.operation_hash() or the advanced query-aware hash")); // QueryHash::new(hash)); + self.schema_aware_hash = Arc::new(todo!( + "Here we need either schema.operation_hash() or the advanced query-aware hash" + )); // QueryHash::new(hash)); Ok(()) } diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index 000026627d..63edfb3be2 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -56,6 +56,7 @@ pub struct QueryPlan { #[buildstructor::buildstructor] impl QueryPlan { #[builder] + #[cfg(test)] pub(crate) fn fake_new( root: Option, usage_reporting: Option, diff --git a/apollo-router/src/router_factory.rs b/apollo-router/src/router_factory.rs index a31fbd4fba..74f7e1ba45 100644 --- a/apollo-router/src/router_factory.rs +++ b/apollo-router/src/router_factory.rs @@ -175,13 +175,15 @@ impl RouterSuperServiceFactory for YamlRouterFactory { .get("telemetry") .cloned(); if let Some(plugin_config) = &mut telemetry_config { - inject_schema_id(Some(&schema.schema_id), plugin_config); + inject_schema_id(schema.schema_id.as_str(), plugin_config); match factory .create_instance( PluginInit::builder() .config(plugin_config.clone()) .supergraph_sdl(schema.raw_sdl.clone()) - .supergraph_schema_id(schema.schema_id.clone()) + .supergraph_schema_id(Arc::new( + schema.schema_id.as_str().to_owned(), + )) .supergraph_schema(Arc::new(schema.supergraph_schema().clone())) .notify(configuration.notify.clone()) .build(), @@ -553,7 +555,7 @@ pub(crate) async fn create_plugins( extra_plugins: Option)>>, ) -> Result { let supergraph_schema = Arc::new(schema.supergraph_schema().clone()); - let supergraph_schema_id = Arc::new(schema.schema_id.to_string()); + let supergraph_schema_id = schema.schema_id.clone().into_inner(); let mut apollo_plugins_config = configuration.apollo_plugins.clone().plugins; let user_plugins_config = configuration.plugins.clone().plugins.unwrap_or_default(); let extra = extra_plugins.unwrap_or_default(); @@ -610,7 +612,7 @@ pub(crate) async fn create_plugins( // give it some. If any of the other mandatory plugins need special // treatment, then we'll have to perform it here. // This is *required* by the telemetry module or it will fail... - inject_schema_id(Some(&supergraph_schema_id), &mut plugin_config); + inject_schema_id(&supergraph_schema_id, &mut plugin_config); } add_plugin!(name.to_string(), factory, plugin_config); } @@ -730,8 +732,12 @@ pub(crate) async fn create_plugins( } } -fn inject_schema_id(schema_id: Option<&str>, configuration: &mut Value) { - if configuration.get("apollo").is_none() { +fn inject_schema_id(schema_id: &str, configuration: &mut Value) { + if let Some(apollo) = configuration.get_mut("apollo") { + if let Some(apollo) = apollo.as_object_mut() { + apollo.insert("schema_id".to_string(), Value::String(schema_id.to_owned())); + } + } else { // Warning: this must be done here, otherwise studio reporting will not work if apollo_key().is_some() && apollo_graph_reference().is_some() { if let Some(telemetry) = configuration.as_object_mut() { @@ -741,14 +747,6 @@ fn inject_schema_id(schema_id: Option<&str>, configuration: &mut Value) { return; } } - if let (Some(schema_id), Some(apollo)) = (schema_id, configuration.get_mut("apollo")) { - if let Some(apollo) = apollo.as_object_mut() { - apollo.insert( - "schema_id".to_string(), - Value::String(schema_id.to_string()), - ); - } - } } #[cfg(test)] @@ -886,7 +884,7 @@ mod test { fn test_inject_schema_id() { let mut config = json!({ "apollo": {} }); inject_schema_id( - Some("8e2021d131b23684671c3b85f82dfca836908c6a541bbd5c3772c66e7f8429d8"), + "8e2021d131b23684671c3b85f82dfca836908c6a541bbd5c3772c66e7f8429d8", &mut config, ); let config = diff --git a/apollo-router/src/spec/query.rs b/apollo-router/src/spec/query.rs index ef0e747593..263d5ff501 100644 --- a/apollo-router/src/spec/query.rs +++ b/apollo-router/src/spec/query.rs @@ -17,11 +17,11 @@ use serde::Serialize; use serde_json_bytes::ByteString; use tracing::level_filters::LevelFilter; -use self::change::QueryHashVisitor; use self::subselections::BooleanValues; use self::subselections::SubSelectionKey; use self::subselections::SubSelectionValue; use super::Fragment; +use super::QueryHash; use crate::error::FetchError; use crate::graphql::Error; use crate::graphql::Request; @@ -73,12 +73,9 @@ pub(crate) struct Query { /// This is a hash that depends on: /// - the query itself - /// - the relevant parts of the schema - /// - /// if a schema update does not affect a query, then this will be the same hash - /// with the old and new schema + /// - the schema #[derivative(PartialEq = "ignore", Hash = "ignore")] - pub(crate) schema_aware_hash: Vec, + pub(crate) schema_aware_hash: QueryHash, } #[derive(Debug, Serialize, Deserialize)] @@ -94,6 +91,7 @@ pub(crate) struct DeferStats { } impl Query { + #[cfg(test)] pub(crate) fn empty() -> Self { Self { string: String::new(), @@ -110,7 +108,7 @@ impl Query { conditional_defer_variable_names: IndexSet::default(), }, is_original: true, - schema_aware_hash: vec![], + schema_aware_hash: QueryHash::default(), } } @@ -285,7 +283,7 @@ impl Query { let doc = Self::parse_document(&query, operation_name, schema, configuration)?; let (fragments, operation, defer_stats, schema_aware_hash) = - Self::extract_query_information(schema, &doc.executable, operation_name)?; + Self::extract_query_information(schema, query, &doc.executable, operation_name)?; Ok(Query { string: query, @@ -303,9 +301,10 @@ impl Query { /// Extract serializable data structures from the apollo-compiler HIR. pub(crate) fn extract_query_information( schema: &Schema, + query: &str, document: &ExecutableDocument, operation_name: Option<&str>, - ) -> Result<(Fragments, Operation, DeferStats, Vec), SpecError> { + ) -> Result<(Fragments, Operation, DeferStats, QueryHash), SpecError> { let mut defer_stats = DeferStats { has_defer: false, has_unconditional_defer: false, @@ -314,15 +313,7 @@ impl Query { let fragments = Fragments::from_hir(document, schema, &mut defer_stats)?; let operation = get_operation(document, operation_name)?; let operation = Operation::from_hir(&operation, schema, &mut defer_stats, &fragments)?; - - let mut visitor = - QueryHashVisitor::new(schema.supergraph_schema(), &schema.raw_sdl, document).map_err( - |e| SpecError::QueryHashing(format!("could not calculate the query hash: {e}")), - )?; - traverse::document(&mut visitor, document, operation_name).map_err(|e| { - SpecError::QueryHashing(format!("could not calculate the query hash: {e}")) - })?; - let hash = visitor.finish(); + let hash = schema.schema_id.operation_hash(query, operation_name); Ok((fragments, operation, defer_stats, hash)) } diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 360888ea28..359d2dbf24 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -375,7 +375,7 @@ pub(crate) struct SchemaId( /// turned into a string as needed. /// But `Arc` is used in the public plugin interface and other places, so this is /// essentially a backwards compatibility decision. - Arc + Arc, ); impl SchemaId { pub(crate) fn new(sdl: &str) -> Self { @@ -398,7 +398,11 @@ impl SchemaId { /// Compute the hash for an executable document and operation name against this schema. /// /// See [QueryHash] for details of what's included. - pub(crate) fn operation_hash(&self, query_text: &str, operation_name: Option<&str>) -> QueryHash { + pub(crate) fn operation_hash( + &self, + query_text: &str, + operation_name: Option<&str>, + ) -> QueryHash { QueryHash::new(self, query_text, operation_name) } } @@ -424,7 +428,8 @@ pub(crate) struct QueryHash( /// Unlike SchemaId, the query hash has no backwards compatibility motivations for the internal /// type, as it's fully private. We could consider making this a fixed-size byte array rather /// than a Vec, but it shouldn't make a huge difference. - #[serde(with = "hex")] Vec + #[serde(with = "hex")] + Vec, ); impl QueryHash { From 866c8075296c9b069e21da9a41b3d0d787fc7767 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Tue, 21 Jan 2025 15:52:26 +0200 Subject: [PATCH 12/38] fix error in entity.rs --- apollo-router/src/plugins/cache/entity.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apollo-router/src/plugins/cache/entity.rs b/apollo-router/src/plugins/cache/entity.rs index 37db0c2619..3a9fc00d6f 100644 --- a/apollo-router/src/plugins/cache/entity.rs +++ b/apollo-router/src/plugins/cache/entity.rs @@ -1222,7 +1222,7 @@ pub(crate) fn hash_vary_headers(headers: &http::HeaderMap) -> String { pub(crate) fn hash_query(query_hash: &QueryHash, body: &graphql::Request) -> String { let mut digest = Sha256::new(); - digest.update(&query_hash.0); + digest.update(query_hash.to_string()); digest.update(&[0u8; 1][..]); digest.update(body.operation_name.as_deref().unwrap_or("-").as_bytes()); digest.update(&[0u8; 1][..]); From ffe1b6cdc3e4b86a0c979f68e3ecd9c9eccb250a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 14:58:00 +0100 Subject: [PATCH 13/38] Fix import of QueryHash inside batching code --- apollo-router/src/batching.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apollo-router/src/batching.rs b/apollo-router/src/batching.rs index f6cdab3e1e..e4283774f4 100644 --- a/apollo-router/src/batching.rs +++ b/apollo-router/src/batching.rs @@ -485,7 +485,7 @@ mod tests { use crate::graphql; use crate::graphql::Request; use crate::layers::ServiceExt as LayerExt; - use crate::query_planner::fetch::QueryHash; + use crate::spec::QueryHash; use crate::services::http::HttpClientServiceFactory; use crate::services::router; use crate::services::subgraph; From 8d30e7e3c81a3c019b50120d8c5578fd6ac79bbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 15:40:13 +0100 Subject: [PATCH 14/38] Pass query text to extract_query_information as necessary --- apollo-router/src/spec/query.rs | 14 +++++++------- apollo-router/src/spec/query/tests.rs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/apollo-router/src/spec/query.rs b/apollo-router/src/spec/query.rs index 263d5ff501..c34d7e2ad5 100644 --- a/apollo-router/src/spec/query.rs +++ b/apollo-router/src/spec/query.rs @@ -274,19 +274,19 @@ impl Query { #[cfg(test)] pub(crate) fn parse( - query: impl Into, + query_text: impl Into, operation_name: Option<&str>, schema: &Schema, configuration: &Configuration, ) -> Result { - let query = query.into(); + let query_text = query_text.into(); - let doc = Self::parse_document(&query, operation_name, schema, configuration)?; + let doc = Self::parse_document(&query_text, operation_name, schema, configuration)?; let (fragments, operation, defer_stats, schema_aware_hash) = - Self::extract_query_information(schema, query, &doc.executable, operation_name)?; + Self::extract_query_information(schema, &query_text, &doc.executable, operation_name)?; Ok(Query { - string: query, + string: query_text, fragments, operation, subselections: HashMap::new(), @@ -301,7 +301,7 @@ impl Query { /// Extract serializable data structures from the apollo-compiler HIR. pub(crate) fn extract_query_information( schema: &Schema, - query: &str, + query_text: &str, document: &ExecutableDocument, operation_name: Option<&str>, ) -> Result<(Fragments, Operation, DeferStats, QueryHash), SpecError> { @@ -313,7 +313,7 @@ impl Query { let fragments = Fragments::from_hir(document, schema, &mut defer_stats)?; let operation = get_operation(document, operation_name)?; let operation = Operation::from_hir(&operation, schema, &mut defer_stats, &fragments)?; - let hash = schema.schema_id.operation_hash(query, operation_name); + let hash = schema.schema_id.operation_hash(query_text, operation_name); Ok((fragments, operation, defer_stats, hash)) } diff --git a/apollo-router/src/spec/query/tests.rs b/apollo-router/src/spec/query/tests.rs index 1d97962405..5b6288adfb 100644 --- a/apollo-router/src/spec/query/tests.rs +++ b/apollo-router/src/spec/query/tests.rs @@ -5766,7 +5766,7 @@ fn filtered_defer_fragment() { .unwrap(); let doc = ast.to_executable(schema.supergraph_schema()).unwrap(); let (fragments, operation, defer_stats, schema_aware_hash) = - Query::extract_query_information(&schema, &doc, None).unwrap(); + Query::extract_query_information(&schema, filtered_query, &doc, None).unwrap(); let subselections = crate::spec::query::subselections::collect_subselections( &config, @@ -5792,7 +5792,7 @@ fn filtered_defer_fragment() { .unwrap(); let doc = ast.to_executable(schema.supergraph_schema()).unwrap(); let (fragments, operation, defer_stats, schema_aware_hash) = - Query::extract_query_information(&schema, &doc, None).unwrap(); + Query::extract_query_information(&schema, filtered_query, &doc, None).unwrap(); let subselections = crate::spec::query::subselections::collect_subselections( &config, From 50d182957bd56d4f7d9d3a82355655095b214a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 16:01:44 +0100 Subject: [PATCH 15/38] Remove `cfg(test)` from `Query::empty` Adding it to all the transitive usage sites is a lot of work. Renamed it for clarity. --- .../src/query_planner/caching_query_planner.rs | 2 +- apollo-router/src/query_planner/plan.rs | 3 +-- apollo-router/src/query_planner/tests.rs | 12 ++++++------ apollo-router/src/spec/query.rs | 7 +++++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index c7a2fbf342..c0e911b4b2 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -879,7 +879,7 @@ mod tests { referenced_fields_by_type: Default::default(), } .into(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), estimated_size: Default::default(), }; diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index 63edfb3be2..eb1d7dcf5e 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -56,7 +56,6 @@ pub struct QueryPlan { #[buildstructor::buildstructor] impl QueryPlan { #[builder] - #[cfg(test)] pub(crate) fn fake_new( root: Option, usage_reporting: Option, @@ -70,7 +69,7 @@ impl QueryPlan { .into(), root: Arc::new(root.unwrap_or_else(|| PlanNode::Sequence { nodes: Vec::new() })), formatted_query_plan: Default::default(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), estimated_size: Default::default(), } diff --git a/apollo-router/src/query_planner/tests.rs b/apollo-router/src/query_planner/tests.rs index 2ab97e9d51..e6cc13c85b 100644 --- a/apollo-router/src/query_planner/tests.rs +++ b/apollo-router/src/query_planner/tests.rs @@ -80,7 +80,7 @@ async fn mock_subgraph_service_withf_panics_should_be_reported_as_service_closed let query_plan: QueryPlan = QueryPlan { root: serde_json::from_str(test_query_plan!()).unwrap(), formatted_query_plan: Default::default(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), usage_reporting: UsageReporting { stats_report_key: "this is a test report key".to_string(), @@ -141,7 +141,7 @@ async fn fetch_includes_operation_name() { referenced_fields_by_type: Default::default(), } .into(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), estimated_size: Default::default(), }; @@ -202,7 +202,7 @@ async fn fetch_makes_post_requests() { referenced_fields_by_type: Default::default(), } .into(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), estimated_size: Default::default(), }; @@ -331,7 +331,7 @@ async fn defer() { stats_report_key: "this is a test report key".to_string(), referenced_fields_by_type: Default::default(), }.into(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), estimated_size: Default::default(), }; @@ -618,7 +618,7 @@ async fn dependent_mutations() { referenced_fields_by_type: Default::default(), } .into(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), estimated_size: Default::default(), }; @@ -1833,7 +1833,7 @@ fn broken_plan_does_not_panic() { referenced_fields_by_type: Default::default(), } .into(), - query: Arc::new(Query::empty()), + query: Arc::new(Query::empty_for_tests()), query_metrics: Default::default(), estimated_size: Default::default(), }; diff --git a/apollo-router/src/spec/query.rs b/apollo-router/src/spec/query.rs index c34d7e2ad5..ad4f56ffac 100644 --- a/apollo-router/src/spec/query.rs +++ b/apollo-router/src/spec/query.rs @@ -91,8 +91,11 @@ pub(crate) struct DeferStats { } impl Query { - #[cfg(test)] - pub(crate) fn empty() -> Self { + /// Returns an empty query. This should be used somewhat carefully and only in tests. + /// Other parts of the router may not handle empty queries properly. + /// + /// FIXME: This should be marked cfg(test) but it's used in places where adding cfg(test) is tricky. + pub(crate) fn empty_for_tests() -> Self { Self { string: String::new(), fragments: Fragments { From c6aa3af896c260fe9f4e6115f221830d62473e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 16:04:06 +0100 Subject: [PATCH 16/38] Fix test assertion --- apollo-router/src/spec/schema.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 359d2dbf24..50f0ffa715 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -675,7 +675,7 @@ mod tests { let schema = Schema::parse(schema, &Default::default()).unwrap(); assert_eq!( - Schema::schema_id(&schema.raw_sdl), + Schema::schema_id(&schema.raw_sdl).as_str(), "23bcf0ea13a4e0429c942bba59573ba70b8d6970d73ad00c5230d08788bb1ba2".to_string() ); } From 879e71ab9931b062112ee8daff5292a19c0cd92e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 16:31:17 +0100 Subject: [PATCH 17/38] Comment how `Request::query_hash` works --- apollo-router/src/services/subgraph.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apollo-router/src/services/subgraph.rs b/apollo-router/src/services/subgraph.rs index fccf04fa34..2f0275ef11 100644 --- a/apollo-router/src/services/subgraph.rs +++ b/apollo-router/src/services/subgraph.rs @@ -102,9 +102,10 @@ impl Request { subgraph_name, subscription_stream, connection_closed_signal, - // XXX: This seems wrong and bad? - // We should figure out how this is used. - query_hash: QueryHash::default(), + // It's NOT GREAT! to have an empty hash value here. + // This value is populated based on the subgraph query hash in the query planner code. + // At the time of writing it's in `crate::query_planner::fetch::FetchNode::fetch_node`. + query_hash: QueryHash::default().into(), authorization: Default::default(), executable_document: None, id: SubgraphRequestId::new(), From 594a7463be4e34b858c36d22c1bd50847fce96ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 16:35:51 +0100 Subject: [PATCH 18/38] Fix lifetime in BridgeQueryPlanner::call --- apollo-router/src/query_planner/bridge_query_planner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index 3ded2d1df9..a59ad1fb9d 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -624,7 +624,7 @@ impl Service for BridgeQueryPlanner { .to_executable_validate(api_schema) // Assume transformation creates a valid document: ignore conversion errors .map_err(|e| SpecError::ValidationError(e.into()))?; - let hash = self + let hash = this .schema .schema_id .operation_hash(&modified_query.to_string(), operation_name.as_deref()); From 68aa91238a3c014298f2747df3e7eb323a1db92a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 16:39:52 +0100 Subject: [PATCH 19/38] Mark ConfigModeHash pub(crate) to appease linter It would be better to make everything not-pub, but let's do that separately. --- apollo-router/src/query_planner/caching_query_planner.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index c0e911b4b2..3093e6414d 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -63,7 +63,9 @@ pub(crate) enum ConfigMode { /// Hashed value of query planner configuration for use in cache keys. #[derive(Clone, Hash, PartialEq, Eq)] -struct ConfigModeHash(Vec); +// XXX(@goto-bus-stop): I think this probably should not be pub(crate), but right now all fields in +// the cache keys are pub(crate), which I'm not going to change at this time :) +pub(crate) struct ConfigModeHash(Vec); impl std::fmt::Display for ConfigModeHash { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { From 9473d13c1d706d3b216721b829c56e7788c2e437 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Tue, 21 Jan 2025 17:42:56 +0200 Subject: [PATCH 20/38] it's building !!! --- .../src/query_planner/bridge_query_planner.rs | 15 ++------ apollo-router/src/query_planner/fetch.rs | 34 +++++++++---------- apollo-router/src/query_planner/plan.rs | 24 ++++++------- 3 files changed, 30 insertions(+), 43 deletions(-) diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index a59ad1fb9d..d843e16f0e 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -369,10 +369,7 @@ impl PlannerMode { .map(|(name, schema)| { ( name.to_string(), - SubgraphSchema { - implementers_map: schema.schema().implementers_map(), - schema: Arc::new(schema.schema().clone()), - }, + SubgraphSchema::new(schema.schema().clone()), ) }) .collect()) @@ -384,13 +381,7 @@ impl PlannerMode { .map(|(name, schema_str)| { let schema = apollo_compiler::Schema::parse_and_validate(schema_str, "") .map_err(|errors| SchemaError::Validate(errors.into()))?; - Ok(( - name, - SubgraphSchema { - implementers_map: schema.implementers_map(), - schema: Arc::new(schema), - }, - )) + Ok((name, SubgraphSchema::new(schema))) }) .collect() } @@ -508,7 +499,7 @@ impl BridgeQueryPlanner { root_node.init_parsed_operations_and_hash_subqueries( &self.subgraph_schemas, &self.schema.raw_sdl, - )?; + ); root_node.extract_authorization_metadata(self.schema.supergraph_schema(), &key); Ok(()) }, diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 4b989ed90e..84397a191f 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -5,7 +5,6 @@ use apollo_compiler::ast; use apollo_compiler::collections::HashMap; use apollo_compiler::validation::Valid; use apollo_compiler::ExecutableDocument; -use apollo_compiler::Name; use indexmap::IndexSet; use serde::Deserialize; use serde::Serialize; @@ -34,9 +33,9 @@ use crate::json_ext::ValueExt; use crate::plugins::authorization::AuthorizationPlugin; use crate::plugins::authorization::CacheKeyMetadata; use crate::services::SubgraphRequest; -use crate::spec::query::change::QueryHashVisitor; use crate::spec::QueryHash; use crate::spec::Schema; +use crate::spec::SchemaId; /// GraphQL operation type. #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, Deserialize, Serialize)] @@ -99,7 +98,18 @@ pub(crate) type SubgraphSchemas = HashMap; pub(crate) struct SubgraphSchema { pub(crate) schema: Arc>, - pub(crate) implementers_map: HashMap, + // TODO: Ideally should have separate nominal type for subgraph's schema hash + pub(crate) hash: Arc, +} + +impl SubgraphSchema { + pub(crate) fn new(schema: Valid) -> Self { + let sdl = schema.to_string(); + Self { + schema: Arc::new(schema), + hash: Arc::new(SchemaId::new(&sdl)), + } + } } /// A fetch node. @@ -677,22 +687,12 @@ impl FetchNode { pub(crate) fn init_parsed_operation_and_hash_subquery( &mut self, subgraph_schemas: &SubgraphSchemas, - supergraph_schema_hash: &str, - ) -> Result<(), ValidationErrors> { + ) { let schema = &subgraph_schemas[self.service_name.as_ref()]; - let doc = self.operation.init_parsed(&schema.schema)?; - - if let Ok(hash) = QueryHashVisitor::hash_query( - &schema.schema, - supergraph_schema_hash, - &schema.implementers_map, - doc, + self.schema_aware_hash = Arc::new(schema.hash.operation_hash( + self.operation.as_serialized(), self.operation_name.as_deref(), - ) {} - self.schema_aware_hash = Arc::new(todo!( - "Here we need either schema.operation_hash() or the advanced query-aware hash" - )); // QueryHash::new(hash)); - Ok(()) + )); } pub(crate) fn extract_authorization_metadata( diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index eb1d7dcf5e..d93c7bda6c 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -379,13 +379,10 @@ impl PlanNode { &mut self, subgraph_schemas: &SubgraphSchemas, supergraph_schema_hash: &str, - ) -> Result<(), ValidationErrors> { + ) { match self { PlanNode::Fetch(fetch_node) => { - fetch_node.init_parsed_operation_and_hash_subquery( - subgraph_schemas, - supergraph_schema_hash, - )?; + fetch_node.init_parsed_operation_and_hash_subquery(subgraph_schemas); } PlanNode::Sequence { nodes } => { @@ -393,7 +390,7 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )?; + ); } } PlanNode::Parallel { nodes } => { @@ -401,26 +398,26 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )?; + ); } } PlanNode::Flatten(flatten) => flatten.node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )?, + ), PlanNode::Defer { primary, deferred } => { if let Some(node) = primary.node.as_mut() { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )?; + ); } for deferred_node in deferred { if let Some(node) = &mut deferred_node.node { Arc::make_mut(node).init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )? + ) } } } @@ -429,7 +426,7 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )?; + ); } } PlanNode::Condition { @@ -441,17 +438,16 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )?; + ); } if let Some(node) = else_clause.as_mut() { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - )?; + ); } } } - Ok(()) } #[cfg(test)] From c83dd839491d95d890c46f63b4d3e70192222a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Tue, 21 Jan 2025 16:51:36 +0100 Subject: [PATCH 21/38] Update test --- apollo-router/src/query_planner/tests.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/apollo-router/src/query_planner/tests.rs b/apollo-router/src/query_planner/tests.rs index e6cc13c85b..8fdd41b674 100644 --- a/apollo-router/src/query_planner/tests.rs +++ b/apollo-router/src/query_planner/tests.rs @@ -1841,15 +1841,9 @@ fn broken_plan_does_not_panic() { let mut subgraph_schemas = HashMap::default(); subgraph_schemas.insert( "X".to_owned(), - query_planner::fetch::SubgraphSchema { - implementers_map: subgraph_schema.implementers_map(), - schema: Arc::new(subgraph_schema), - }, + query_planner::fetch::SubgraphSchema::new(subgraph_schema), ); - let result = Arc::make_mut(&mut plan.root) + // Run the plan initialization code to make sure it doesn't panic. + let _result = Arc::make_mut(&mut plan.root) .init_parsed_operations_and_hash_subqueries(&subgraph_schemas, ""); - assert_eq!( - result.unwrap_err().to_string(), - r#"[1:3] Cannot query field "invalid" on type "Query"."# - ); } From 8fe5095a791efb1f126657c70dc35bb1e58e4bd6 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Tue, 21 Jan 2025 17:53:15 +0200 Subject: [PATCH 22/38] remove "Schema aware query hashing algorithm" --- apollo-router/src/spec/query.rs | 1 - apollo-router/src/spec/query/change.rs | 2667 ------------------------ 2 files changed, 2668 deletions(-) delete mode 100644 apollo-router/src/spec/query/change.rs diff --git a/apollo-router/src/spec/query.rs b/apollo-router/src/spec/query.rs index ad4f56ffac..d3c59b7117 100644 --- a/apollo-router/src/spec/query.rs +++ b/apollo-router/src/spec/query.rs @@ -44,7 +44,6 @@ use crate::spec::Selection; use crate::spec::SpecError; use crate::Configuration; -pub(crate) mod change; pub(crate) mod subselections; pub(crate) mod transform; pub(crate) mod traverse; diff --git a/apollo-router/src/spec/query/change.rs b/apollo-router/src/spec/query/change.rs deleted file mode 100644 index 25481139ed..0000000000 --- a/apollo-router/src/spec/query/change.rs +++ /dev/null @@ -1,2667 +0,0 @@ -//! Schema aware query hashing algorithm -//! -//! This is a query visitor that calculates a hash of all fields, along with all -//! the relevant types and directives in the schema. It is designed to generate -//! the same hash for the same query across schema updates if the schema change -//! would not affect that query. As an example, if a new type is added to the -//! schema, we know that it will have no impact to an existing query that cannot -//! be using it. -//! This algorithm is used in 2 places: -//! * in the query planner cache: generating query plans can be expensive, so the -//! router has a warm up feature, where upon receving a new schema, it will take -//! the most used queries and plan them, before switching traffic to the new -//! schema. Generating all of those plans takes a lot of time. By using this -//! hashing algorithm, we can detect that the schema change does not affect the -//! query, which means that we can reuse the old query plan directly and avoid -//! the expensive planning task -//! * in entity caching: the responses returned by subgraphs can change depending -//! on the schema (example: a field moving from String to Int), so we need to -//! detect that. One way to do it was to add the schema hash to the cache key, but -//! as a result it wipes the cache on every schema update, which will cause -//! performance and reliability issues. With this hashing algorithm, cached entries -//! can be kept across schema updates -//! -//! ## Technical details -//! -//! ### Query string hashing -//! A full hash of the query string is added along with the schema level data. This -//! is technically making the algorithm less useful, because the same query with -//! different indentation would get a different hash, while there would be no difference -//! in the query plan or the subgraph response. But this makes sure that if we forget -//! something in the way we hash the query, we will avoid collisions. -//! -//! ### Prefixes and suffixes -//! Across the entire visitor, we add prefixes and suffixes like this: -//! -//! ```rust -//! "^SCHEMA".hash(self); -//! ``` -//! -//! This prevents possible collision while hashing multiple things in a sequence. The -//! `^` character cannot be present in GraphQL names, so this is a good separator. -use std::hash::Hash; -use std::hash::Hasher; - -use apollo_compiler::ast; -use apollo_compiler::ast::FieldDefinition; -use apollo_compiler::collections::HashMap; -use apollo_compiler::collections::HashSet; -use apollo_compiler::executable; -use apollo_compiler::parser::Parser; -use apollo_compiler::schema; -use apollo_compiler::schema::DirectiveList; -use apollo_compiler::schema::ExtendedType; -use apollo_compiler::schema::InterfaceType; -use apollo_compiler::validation::Valid; -use apollo_compiler::Name; -use apollo_compiler::Node; -use sha2::Digest; -use sha2::Sha256; -use tower::BoxError; - -use super::traverse; -use super::traverse::Visitor; -use crate::plugins::progressive_override::JOIN_FIELD_DIRECTIVE_NAME; -use crate::plugins::progressive_override::JOIN_SPEC_BASE_URL; -use crate::spec::Schema; - -pub(crate) const JOIN_TYPE_DIRECTIVE_NAME: &str = "join__type"; -pub(crate) const CONTEXT_SPEC_BASE_URL: &str = "https://specs.apollo.dev/context"; -pub(crate) const CONTEXT_DIRECTIVE_NAME: &str = "context"; - -/// Calculates a hash of the query and the schema, but only looking at the parts of the -/// schema which affect the query. -/// This means that if a schema update does not affect an existing query (example: adding a field), -/// then the hash will stay the same -pub(crate) struct QueryHashVisitor<'a> { - schema: &'a schema::Schema, - // TODO: remove once introspection has been moved out of query planning - // For now, introspection is still handled by the planner, so when an - // introspection query is hashed, it should take the whole schema into account - schema_str: &'a str, - implementers_map: &'a HashMap, - hasher: Sha256, - fragments: HashMap<&'a Name, &'a Node>, - hashed_types: HashSet, - hashed_field_definitions: HashSet<(String, String)>, - seen_introspection: bool, - join_field_directive_name: Option, - join_type_directive_name: Option, - context_directive_name: Option, - // map from context string to list of type names - contexts: HashMap>, -} - -impl<'a> QueryHashVisitor<'a> { - pub(crate) fn new( - schema: &'a schema::Schema, - schema_str: &'a str, - implementers_map: &'a HashMap, - executable: &'a executable::ExecutableDocument, - ) -> Result { - let mut visitor = Self { - schema, - schema_str, - implementers_map, - hasher: Sha256::new(), - fragments: executable.fragments.iter().collect(), - hashed_types: HashSet::default(), - hashed_field_definitions: HashSet::default(), - seen_introspection: false, - // should we just return an error if we do not find those directives? - join_field_directive_name: Schema::directive_name( - schema, - JOIN_SPEC_BASE_URL, - ">=0.1.0", - JOIN_FIELD_DIRECTIVE_NAME, - ), - join_type_directive_name: Schema::directive_name( - schema, - JOIN_SPEC_BASE_URL, - ">=0.1.0", - JOIN_TYPE_DIRECTIVE_NAME, - ), - context_directive_name: Schema::directive_name( - schema, - CONTEXT_SPEC_BASE_URL, - ">=0.1.0", - CONTEXT_DIRECTIVE_NAME, - ), - contexts: HashMap::default(), - }; - - visitor.hash_schema()?; - - Ok(visitor) - } - - pub(crate) fn hash_schema(&mut self) -> Result<(), BoxError> { - "^SCHEMA".hash(self); - for directive_definition in self.schema.directive_definitions.values() { - self.hash_directive_definition(directive_definition)?; - } - - self.hash_directive_list_schema(&self.schema.schema_definition.directives); - - "^SCHEMA-END".hash(self); - Ok(()) - } - - pub(crate) fn hash_query( - schema: &'a schema::Schema, - schema_str: &'a str, - implementers_map: &'a HashMap, - executable: &'a executable::ExecutableDocument, - operation_name: Option<&str>, - ) -> Result, BoxError> { - let mut visitor = QueryHashVisitor::new(schema, schema_str, implementers_map, executable)?; - traverse::document(&mut visitor, executable, operation_name)?; - // hash the entire query string to prevent collisions - executable.to_string().hash(&mut visitor); - Ok(visitor.finish()) - } - - pub(crate) fn finish(self) -> Vec { - self.hasher.finalize().as_slice().into() - } - - fn hash_directive_definition( - &mut self, - directive_definition: &Node, - ) -> Result<(), BoxError> { - "^DIRECTIVE_DEFINITION".hash(self); - directive_definition.name.as_str().hash(self); - "^ARGUMENT_LIST".hash(self); - for argument in &directive_definition.arguments { - self.hash_input_value_definition(argument)?; - } - "^ARGUMENT_LIST_END".hash(self); - - "^DIRECTIVE_DEFINITION-END".hash(self); - - Ok(()) - } - - fn hash_directive_list_schema(&mut self, directive_list: &schema::DirectiveList) { - "^DIRECTIVE_LIST".hash(self); - for directive in directive_list { - self.hash_directive(directive); - } - "^DIRECTIVE_LIST_END".hash(self); - } - - fn hash_directive_list_ast(&mut self, directive_list: &ast::DirectiveList) { - "^DIRECTIVE_LIST".hash(self); - for directive in directive_list { - self.hash_directive(directive); - } - "^DIRECTIVE_LIST_END".hash(self); - } - - fn hash_directive(&mut self, directive: &Node) { - "^DIRECTIVE".hash(self); - directive.name.as_str().hash(self); - "^ARGUMENT_LIST".hash(self); - for argument in &directive.arguments { - self.hash_argument(argument); - } - "^ARGUMENT_END".hash(self); - - "^DIRECTIVE-END".hash(self); - } - - fn hash_argument(&mut self, argument: &Node) { - "^ARGUMENT".hash(self); - argument.name.hash(self); - self.hash_value(&argument.value); - "^ARGUMENT-END".hash(self); - } - - fn hash_value(&mut self, value: &ast::Value) { - "^VALUE".hash(self); - - match value { - schema::Value::Null => "^null".hash(self), - schema::Value::Enum(e) => { - "^enum".hash(self); - e.hash(self); - } - schema::Value::Variable(v) => { - "^variable".hash(self); - v.hash(self); - } - schema::Value::String(s) => { - "^string".hash(self); - s.hash(self); - } - schema::Value::Float(f) => { - "^float".hash(self); - f.hash(self); - } - schema::Value::Int(i) => { - "^int".hash(self); - i.hash(self); - } - schema::Value::Boolean(b) => { - "^boolean".hash(self); - b.hash(self); - } - schema::Value::List(l) => { - "^list[".hash(self); - for v in l.iter() { - self.hash_value(v); - } - "^]".hash(self); - } - schema::Value::Object(o) => { - "^object{".hash(self); - for (k, v) in o.iter() { - "^key".hash(self); - - k.hash(self); - "^value:".hash(self); - self.hash_value(v); - } - "^}".hash(self); - } - } - "^VALUE-END".hash(self); - } - - fn hash_type_by_name(&mut self, name: &str) -> Result<(), BoxError> { - "^TYPE_BY_NAME".hash(self); - - name.hash(self); - - // we need this this to avoid an infinite loop when hashing types that refer to each other - if self.hashed_types.contains(name) { - return Ok(()); - } - - self.hashed_types.insert(name.to_string()); - - if let Some(ty) = self.schema.types.get(name) { - self.hash_extended_type(ty)?; - } - "^TYPE_BY_NAME-END".hash(self); - - Ok(()) - } - - fn hash_extended_type(&mut self, t: &'a ExtendedType) -> Result<(), BoxError> { - "^EXTENDED_TYPE".hash(self); - - match t { - ExtendedType::Scalar(s) => { - "^SCALAR".hash(self); - self.hash_directive_list_schema(&s.directives); - "^SCALAR_END".hash(self); - } - // this only hashes the type level info, not the fields, because those will be taken from the query - // we will still hash the fields using for the key - ExtendedType::Object(o) => { - "^OBJECT".hash(self); - - self.hash_directive_list_schema(&o.directives); - - self.hash_join_type(&o.name, &o.directives)?; - - self.record_context(&o.name, &o.directives)?; - - "^IMPLEMENTED_INTERFACES_LIST".hash(self); - for interface in &o.implements_interfaces { - self.hash_type_by_name(&interface.name)?; - } - "^IMPLEMENTED_INTERFACES_LIST_END".hash(self); - "^OBJECT_END".hash(self); - } - ExtendedType::Interface(i) => { - "^INTERFACE".hash(self); - - self.hash_directive_list_schema(&i.directives); - - self.hash_join_type(&i.name, &i.directives)?; - - self.record_context(&i.name, &i.directives)?; - - "^IMPLEMENTED_INTERFACES_LIST".hash(self); - for implementor in &i.implements_interfaces { - self.hash_type_by_name(&implementor.name)?; - } - "^IMPLEMENTED_INTERFACES_LIST_END".hash(self); - - if let Some(implementers) = self.implementers_map.get(&i.name) { - "^IMPLEMENTER_OBJECT_LIST".hash(self); - - for object in &implementers.objects { - self.hash_type_by_name(object)?; - } - "^IMPLEMENTER_OBJECT_LIST_END".hash(self); - - "^IMPLEMENTER_INTERFACE_LIST".hash(self); - for interface in &implementers.interfaces { - self.hash_type_by_name(interface)?; - } - "^IMPLEMENTER_INTERFACE_LIST_END".hash(self); - } - - "^INTERFACE_END".hash(self); - } - ExtendedType::Union(u) => { - "^UNION".hash(self); - - self.hash_directive_list_schema(&u.directives); - - self.record_context(&u.name, &u.directives)?; - - "^MEMBER_LIST".hash(self); - for member in &u.members { - self.hash_type_by_name(member.as_str())?; - } - "^MEMBER_LIST_END".hash(self); - "^UNION_END".hash(self); - } - ExtendedType::Enum(e) => { - "^ENUM".hash(self); - - self.hash_directive_list_schema(&e.directives); - - "^ENUM_VALUE_LIST".hash(self); - for (value, def) in &e.values { - "^VALUE".hash(self); - - value.hash(self); - self.hash_directive_list_ast(&def.directives); - "^VALUE_END".hash(self); - } - "^ENUM_VALUE_LIST_END".hash(self); - "^ENUM_END".hash(self); - } - ExtendedType::InputObject(o) => { - "^INPUT_OBJECT".hash(self); - self.hash_directive_list_schema(&o.directives); - - "^FIELD_LIST".hash(self); - for (name, ty) in &o.fields { - "^NAME".hash(self); - name.hash(self); - - "^ARGUMENT".hash(self); - self.hash_input_value_definition(&ty.node)?; - } - "^FIELD_LIST_END".hash(self); - "^INPUT_OBJECT_END".hash(self); - } - } - "^EXTENDED_TYPE-END".hash(self); - - Ok(()) - } - - fn hash_type(&mut self, t: &ast::Type) -> Result<(), BoxError> { - "^TYPE".hash(self); - - match t { - schema::Type::Named(name) => self.hash_type_by_name(name.as_str())?, - schema::Type::NonNullNamed(name) => { - "!".hash(self); - self.hash_type_by_name(name.as_str())?; - } - schema::Type::List(t) => { - "[]".hash(self); - self.hash_type(t)?; - } - schema::Type::NonNullList(t) => { - "[]!".hash(self); - self.hash_type(t)?; - } - } - "^TYPE-END".hash(self); - Ok(()) - } - - fn hash_field( - &mut self, - parent_type: &str, - field_def: &FieldDefinition, - node: &executable::Field, - ) -> Result<(), BoxError> { - "^FIELD".hash(self); - self.hash_field_definition(parent_type, field_def)?; - - "^ARGUMENT_LIST".hash(self); - for argument in &node.arguments { - self.hash_argument(argument); - } - "^ARGUMENT_LIST_END".hash(self); - - self.hash_directive_list_ast(&node.directives); - - node.alias.hash(self); - "^FIELD-END".hash(self); - - Ok(()) - } - - fn hash_field_definition( - &mut self, - parent_type: &str, - field_def: &FieldDefinition, - ) -> Result<(), BoxError> { - "^FIELD_DEFINITION".hash(self); - - let field_index = (parent_type.to_string(), field_def.name.as_str().to_string()); - if self.hashed_field_definitions.contains(&field_index) { - return Ok(()); - } - - self.hashed_field_definitions.insert(field_index); - - self.hash_type_by_name(parent_type)?; - - field_def.name.hash(self); - self.hash_type(&field_def.ty)?; - - // for every field, we also need to look at fields defined in `@requires` because - // they will affect the query plan - self.hash_join_field(parent_type, &field_def.directives)?; - - self.hash_directive_list_ast(&field_def.directives); - - "^ARGUMENT_DEF_LIST".hash(self); - for argument in &field_def.arguments { - self.hash_input_value_definition(argument)?; - } - "^ARGUMENT_DEF_LIST_END".hash(self); - - "^FIELD_DEFINITION_END".hash(self); - - Ok(()) - } - - fn hash_input_value_definition( - &mut self, - t: &Node, - ) -> Result<(), BoxError> { - "^INPUT_VALUE".hash(self); - - self.hash_type(&t.ty)?; - self.hash_directive_list_ast(&t.directives); - - if let Some(value) = t.default_value.as_ref() { - self.hash_value(value); - } else { - "^INPUT_VALUE-NO_DEFAULT".hash(self); - } - "^INPUT_VALUE-END".hash(self); - Ok(()) - } - - fn hash_join_type(&mut self, name: &Name, directives: &DirectiveList) -> Result<(), BoxError> { - "^JOIN_TYPE".hash(self); - - if let Some(dir_name) = self.join_type_directive_name.as_deref() { - if let Some(dir) = directives.get(dir_name) { - if let Some(key) = dir - .specified_argument_by_name("key") - .and_then(|arg| arg.as_str()) - { - let mut parser = Parser::new(); - if let Ok(field_set) = parser.parse_field_set( - Valid::assume_valid_ref(self.schema), - name.clone(), - key, - std::path::Path::new("schema.graphql"), - ) { - traverse::selection_set( - self, - name.as_str(), - &field_set.selection_set.selections[..], - )?; - } - } - } - } - "^JOIN_TYPE-END".hash(self); - - Ok(()) - } - - fn hash_join_field( - &mut self, - parent_type: &str, - directives: &ast::DirectiveList, - ) -> Result<(), BoxError> { - "^JOIN_FIELD".hash(self); - - if let Some(dir_name) = self.join_field_directive_name.as_deref() { - if let Some(dir) = directives.get(dir_name) { - if let Some(requires) = dir - .specified_argument_by_name("requires") - .and_then(|arg| arg.as_str()) - { - if let Ok(parent_type) = Name::new(parent_type) { - let mut parser = Parser::new(); - - if let Ok(field_set) = parser.parse_field_set( - Valid::assume_valid_ref(self.schema), - parent_type.clone(), - requires, - std::path::Path::new("schema.graphql"), - ) { - traverse::selection_set( - self, - parent_type.as_str(), - &field_set.selection_set.selections[..], - )?; - } - } - } - - if let Some(context_arguments) = dir - .specified_argument_by_name("contextArguments") - .and_then(|value| value.as_list()) - { - for argument in context_arguments { - self.hash_context_argument(argument)?; - } - } - } - } - "^JOIN_FIELD-END".hash(self); - - Ok(()) - } - - fn record_context( - &mut self, - parent_type: &str, - directives: &DirectiveList, - ) -> Result<(), BoxError> { - if let Some(dir_name) = self.context_directive_name.as_deref() { - if let Some(dir) = directives.get(dir_name) { - if let Some(name) = dir - .specified_argument_by_name("name") - .and_then(|arg| arg.as_str()) - { - self.contexts - .entry(name.to_string()) - .or_default() - .push(parent_type.to_string()); - } - } - } - Ok(()) - } - - /// Hashes the context argument of a field - /// - /// contextArgument contains a selection that must be applied to a parent type in the - /// query that matches the context name. We store in advance which type names map to - /// which contexts, to reuse them here when we encounter the selection. - fn hash_context_argument(&mut self, argument: &ast::Value) -> Result<(), BoxError> { - if let Some(obj) = argument.as_object() { - let context_name = Name::new("context")?; - let selection_name = Name::new("selection")?; - // the contextArgument input type is defined as follows: - // input join__ContextArgument { - // name: String! - // type: String! - // context: String! - // selection: join__FieldValue! - // } - // and that is checked by schema validation, so the `context` and `selection` fields - // are guaranteed to be present and to be strings. - if let (Some(context), Some(selection)) = ( - obj.iter() - .find(|(k, _)| k == &context_name) - .and_then(|(_, v)| v.as_str()), - obj.iter() - .find(|(k, _)| k == &selection_name) - .and_then(|(_, v)| v.as_str()), - ) { - if let Some(types) = self.contexts.get(context).cloned() { - for ty in types { - if let Ok(parent_type) = Name::new(ty.as_str()) { - let mut parser = Parser::new(); - - // we assume that the selection was already checked by schema validation - if let Ok(field_set) = parser.parse_field_set( - Valid::assume_valid_ref(self.schema), - parent_type.clone(), - selection, - std::path::Path::new("schema.graphql"), - ) { - traverse::selection_set( - self, - parent_type.as_str(), - &field_set.selection_set.selections[..], - )?; - } - } - } - } - } - Ok(()) - } else { - Err("context argument value is not an object".into()) - } - } - - fn hash_interface_implementers( - &mut self, - intf: &InterfaceType, - node: &executable::Field, - ) -> Result<(), BoxError> { - "^INTERFACE_IMPL".hash(self); - - if let Some(implementers) = self.implementers_map.get(&intf.name) { - "^IMPLEMENTER_LIST".hash(self); - for object in &implementers.objects { - self.hash_type_by_name(object)?; - traverse::selection_set(self, object, &node.selection_set.selections)?; - } - "^IMPLEMENTER_LIST_END".hash(self); - } - - "^INTERFACE_IMPL-END".hash(self); - Ok(()) - } -} - -impl<'a> Hasher for QueryHashVisitor<'a> { - fn finish(&self) -> u64 { - unreachable!() - } - - fn write(&mut self, bytes: &[u8]) { - // byte separator between each part that is hashed - self.hasher.update(&[0xFF][..]); - self.hasher.update(bytes); - } -} - -impl<'a> Visitor for QueryHashVisitor<'a> { - fn operation(&mut self, root_type: &str, node: &executable::Operation) -> Result<(), BoxError> { - "^VISIT_OPERATION".hash(self); - - root_type.hash(self); - self.hash_type_by_name(root_type)?; - node.operation_type.hash(self); - node.name.hash(self); - - "^VARIABLE_LIST".hash(self); - for variable in &node.variables { - variable.name.hash(self); - self.hash_type(&variable.ty)?; - - if let Some(value) = variable.default_value.as_ref() { - self.hash_value(value); - } else { - "^VISIT_OPERATION-NO_DEFAULT".hash(self); - } - - self.hash_directive_list_ast(&variable.directives); - } - "^VARIABLE_LIST_END".hash(self); - - self.hash_directive_list_ast(&node.directives); - - traverse::operation(self, root_type, node)?; - "^VISIT_OPERATION-END".hash(self); - Ok(()) - } - - fn field( - &mut self, - parent_type: &str, - field_def: &ast::FieldDefinition, - node: &executable::Field, - ) -> Result<(), BoxError> { - "^VISIT_FIELD".hash(self); - - if !self.seen_introspection && (field_def.name == "__schema" || field_def.name == "__type") - { - self.seen_introspection = true; - self.schema_str.hash(self); - } - - self.hash_field(parent_type, field_def, node)?; - - if let Some(ExtendedType::Interface(intf)) = - self.schema.types.get(field_def.ty.inner_named_type()) - { - self.hash_interface_implementers(intf, node)?; - } - - traverse::field(self, field_def, node)?; - "^VISIT_FIELD_END".hash(self); - Ok(()) - } - - fn fragment(&mut self, node: &executable::Fragment) -> Result<(), BoxError> { - "^VISIT_FRAGMENT".hash(self); - - node.name.hash(self); - self.hash_type_by_name(node.type_condition())?; - - self.hash_directive_list_ast(&node.directives); - - traverse::fragment(self, node)?; - "^VISIT_FRAGMENT-END".hash(self); - - Ok(()) - } - - fn fragment_spread(&mut self, node: &executable::FragmentSpread) -> Result<(), BoxError> { - "^VISIT_FRAGMENT_SPREAD".hash(self); - - node.fragment_name.hash(self); - let type_condition = &self - .fragments - .get(&node.fragment_name) - .ok_or("MissingFragment")? - .type_condition(); - self.hash_type_by_name(type_condition)?; - - self.hash_directive_list_ast(&node.directives); - - traverse::fragment_spread(self, node)?; - "^VISIT_FRAGMENT_SPREAD-END".hash(self); - - Ok(()) - } - - fn inline_fragment( - &mut self, - parent_type: &str, - node: &executable::InlineFragment, - ) -> Result<(), BoxError> { - "^VISIT_INLINE_FRAGMENT".hash(self); - - if let Some(type_condition) = &node.type_condition { - self.hash_type_by_name(type_condition)?; - } - self.hash_directive_list_ast(&node.directives); - - traverse::inline_fragment(self, parent_type, node)?; - "^VISIT_INLINE_FRAGMENT-END".hash(self); - Ok(()) - } - - fn schema(&self) -> &apollo_compiler::Schema { - self.schema - } -} - -#[cfg(test)] -mod tests { - use apollo_compiler::ast::Document; - use apollo_compiler::schema::Schema; - use apollo_compiler::validation::Valid; - - use super::QueryHashVisitor; - use crate::spec::query::traverse; - - #[derive(Debug)] - struct HashComparator { - from_visitor: String, - from_hash_query: String, - } - - impl From<(String, String)> for HashComparator { - fn from(value: (String, String)) -> Self { - Self { - from_visitor: value.0, - from_hash_query: value.1, - } - } - } - - // The non equality check is not the same - // as one would expect from PartialEq. - // This is why HashComparator doesn't implement it. - impl HashComparator { - fn equals(&self, other: &Self) -> bool { - self.from_visitor == other.from_visitor && self.from_hash_query == other.from_hash_query - } - fn doesnt_match(&self, other: &Self) -> bool { - // This is intentional, we check to prevent BOTH hashes from being equal - self.from_visitor != other.from_visitor && self.from_hash_query != other.from_hash_query - } - } - - #[track_caller] - fn hash(schema_str: &str, query: &str) -> HashComparator { - let schema = Schema::parse(schema_str, "schema.graphql") - .unwrap() - .validate() - .unwrap(); - let doc = Document::parse(query, "query.graphql").unwrap(); - - let exec = doc - .to_executable(&schema) - .unwrap() - .validate(&schema) - .unwrap(); - let implementers_map = schema.implementers_map(); - let mut visitor = - QueryHashVisitor::new(&schema, schema_str, &implementers_map, &exec).unwrap(); - traverse::document(&mut visitor, &exec, None).unwrap(); - - ( - hex::encode(visitor.finish()), - hex::encode( - QueryHashVisitor::hash_query(&schema, schema_str, &implementers_map, &exec, None) - .unwrap(), - ), - ) - .into() - } - - #[track_caller] - fn hash_subgraph_query(schema_str: &str, query: &str) -> String { - let schema = Valid::assume_valid(Schema::parse(schema_str, "schema.graphql").unwrap()); - let doc = Document::parse(query, "query.graphql").unwrap(); - let exec = doc - .to_executable(&schema) - .unwrap() - .validate(&schema) - .unwrap(); - let implementers_map = schema.implementers_map(); - let mut visitor = - QueryHashVisitor::new(&schema, schema_str, &implementers_map, &exec).unwrap(); - traverse::document(&mut visitor, &exec, None).unwrap(); - - hex::encode(visitor.finish()) - } - - #[test] - fn me() { - let schema1: &str = r#" - type Query { - me: User - customer: User - } - - type User { - id: ID - name: String - } - "#; - - let schema2: &str = r#" - type Query { - me: User - } - - - type User { - id: ID! - name: String - } - "#; - let query = "query { me { name } }"; - assert!(hash(schema1, query).equals(&hash(schema2, query))); - - // id is nullable in 1, non nullable in 2 - let query = "query { me { id name } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - // simple normalization - let query = "query { moi: me { name } }"; - assert!(hash(schema1, query).equals(&hash(schema2, query))); - - assert!(hash(schema1, "query { me { id name } }") - .doesnt_match(&hash(schema1, "query { me { name id } }"))); - } - - #[test] - fn directive() { - let schema1: &str = r#" - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM | UNION | INPUT_OBJECT - - type Query { - me: User - customer: User - s: S - u: U - e: E - inp(i: I): ID - } - - type User { - id: ID! - name: String - } - - scalar S - - type A { - a: ID - } - - type B { - b: ID - } - - union U = A | B - - enum E { - A - B - } - - input I { - a: Int = 0 - b: Int - } - "#; - - let schema2: &str = r#" - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM | UNION | INPUT_OBJECT - - type Query { - me: User - customer: User @test - s: S - u: U - e: E - inp(i: I): ID - } - - type User { - id: ID! @test - name: String - } - - scalar S @test - - type A { - a: ID - } - - type B { - b: ID - } - - union U @test = A | B - - enum E @test { - A - B - } - - - input I @test { - a: Int = 0 - b: Int - } - "#; - let query = "query { me { name } }"; - assert!(hash(schema1, query).equals(&hash(schema2, query))); - - let query = "query { me { id name } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { customer { id } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { s }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { u { ...on A { a } ...on B { b } } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { e }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { inp(i: { b: 0 }) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn interface() { - let schema1: &str = r#" - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM - - type Query { - me: User - customer: I - } - - interface I { - id: ID - } - - type User implements I { - id: ID! - name: String - } - "#; - - let schema2: &str = r#" - schema { - query: Query - } - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM - - type Query { - me: User - customer: I - } - - interface I @test { - id: ID - } - - type User implements I { - id: ID! - name: String - } - "#; - - let query = "query { me { id name } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { customer { id } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { customer { ... on User { name } } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn arguments_int() { - let schema1: &str = r#" - type Query { - a(i: Int): Int - b(i: Int = 1): Int - c(i: Int = 1, j: Int = null): Int - } - "#; - - let schema2: &str = r#" - type Query { - a(i: Int!): Int - b(i: Int = 2): Int - c(i: Int = 2, j: Int = null): Int - } - "#; - - let query = "query { a(i: 0) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b(i: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { c(j: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { c(i:0, j: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn arguments_float() { - let schema1: &str = r#" - type Query { - a(i: Float): Int - b(i: Float = 1.0): Int - c(i: Float = 1.0, j: Int): Int - } - "#; - - let schema2: &str = r#" - type Query { - a(i: Float!): Int - b(i: Float = 2.0): Int - c(i: Float = 2.0, j: Int): Int - } - "#; - - let query = "query { a(i: 0) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b(i: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { c(j: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { c(i:0, j: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn arguments_list() { - let schema1: &str = r#" - type Query { - a(i: [Float]): Int - b(i: [Float] = [1.0]): Int - c(i: [Float] = [1.0], j: Int): Int - } - "#; - - let schema2: &str = r#" - type Query { - a(i: [Float!]): Int - b(i: [Float] = [2.0]): Int - c(i: [Float] = [2.0], j: Int): Int - } - "#; - - let query = "query { a(i: [0]) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b(i: [0])}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { c(j: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { c(i: [0], j: 0)}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn arguments_object() { - let schema1: &str = r#" - input T { - d: Int - e: String - } - input U { - c: Int - } - input V { - d: Int = 0 - } - - type Query { - a(i: T): Int - b(i: T = { d: 1, e: "a" }): Int - c(c: U): Int - d(d: V): Int - } - "#; - - let schema2: &str = r#" - input T { - d: Int - e: String - } - input U { - c: Int! - } - input V { - d: Int = 1 - } - - type Query { - a(i: T!): Int - b(i: T = { d: 2, e: "b" }): Int - c(c: U): Int - d(d: V): Int - } - "#; - - let query = "query { a(i: { d: 1, e: \"a\" }) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { b(i: { d: 3, e: \"c\" })}"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { c(c: { c: 0 }) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { d(d: { }) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { d(d: { d: 2 }) }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn entities() { - let schema1: &str = r#" - scalar _Any - - union _Entity = User - - type Query { - _entities(representations: [_Any!]!): [_Entity]! - me: User - customer: User - } - - type User { - id: ID - name: String - } - "#; - - let schema2: &str = r#" - scalar _Any - - union _Entity = User - - type Query { - _entities(representations: [_Any!]!): [_Entity]! - me: User - } - - - type User { - id: ID! - name: String - } - "#; - - let query1 = r#"query Query1($representations:[_Any!]!){ - _entities(representations:$representations){ - ...on User { - id - name - } - } - }"#; - - let hash1 = hash_subgraph_query(schema1, query1); - let hash2 = hash_subgraph_query(schema2, query1); - assert_ne!(hash1, hash2); - - let query2 = r#"query Query1($representations:[_Any!]!){ - _entities(representations:$representations){ - ...on User { - name - } - } - }"#; - - let hash1 = hash_subgraph_query(schema1, query2); - let hash2 = hash_subgraph_query(schema2, query2); - assert_eq!(hash1, hash2); - } - - #[test] - fn join_type_key() { - let schema1: &str = r#" - schema - @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) { - query: Query - } - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM - directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on OBJECT | INTERFACE - directive @join__graph(name: String!, url: String!) on ENUM_VALUE - directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA - - scalar join__FieldSet - - scalar link__Import - - enum link__Purpose { - """ - `SECURITY` features provide metadata necessary to securely resolve fields. - """ - SECURITY - - """ - `EXECUTION` features provide metadata necessary for operation execution. - """ - EXECUTION - } - - enum join__Graph { - ACCOUNTS @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev") - INVENTORY @join__graph(name: "inventory", url: "https://inventory.demo.starstuff.dev") - PRODUCTS @join__graph(name: "products", url: "https://products.demo.starstuff.dev") - REVIEWS @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev") - } - - type Query { - me: User - customer: User - itf: I - } - - type User @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name: String - } - - interface I @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name :String - } - - union U = User - "#; - - let schema2: &str = r#" - schema - @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) { - query: Query - } - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM - directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on OBJECT | INTERFACE - directive @join__graph(name: String!, url: String!) on ENUM_VALUE - directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA - - scalar join__FieldSet - - scalar link__Import - - enum link__Purpose { - """ - `SECURITY` features provide metadata necessary to securely resolve fields. - """ - SECURITY - - """ - `EXECUTION` features provide metadata necessary for operation execution. - """ - EXECUTION - } - - enum join__Graph { - ACCOUNTS @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev") - INVENTORY @join__graph(name: "inventory", url: "https://inventory.demo.starstuff.dev") - PRODUCTS @join__graph(name: "products", url: "https://products.demo.starstuff.dev") - REVIEWS @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev") - } - - type Query { - me: User - customer: User @test - itf: I - } - - type User @join__type(graph: ACCOUNTS, key: "id") { - id: ID! @test - name: String - } - - interface I @join__type(graph: ACCOUNTS, key: "id") { - id: ID! @test - name :String - } - "#; - let query = "query { me { name } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { itf { name } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn join_field_requires() { - let schema1: &str = r#" - schema - @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) { - query: Query - } - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM - directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on OBJECT | INTERFACE - directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION - directive @join__graph(name: String!, url: String!) on ENUM_VALUE - directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA - - scalar join__FieldSet - - scalar link__Import - - enum link__Purpose { - """ - `SECURITY` features provide metadata necessary to securely resolve fields. - """ - SECURITY - - """ - `EXECUTION` features provide metadata necessary for operation execution. - """ - EXECUTION - } - - enum join__Graph { - ACCOUNTS @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev") - INVENTORY @join__graph(name: "inventory", url: "https://inventory.demo.starstuff.dev") - PRODUCTS @join__graph(name: "products", url: "https://products.demo.starstuff.dev") - REVIEWS @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev") - } - - type Query { - me: User - customer: User - itf: I - } - - type User @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name: String - username: String @join__field(graph:ACCOUNTS, requires: "name") - a: String @join__field(graph:ACCOUNTS, requires: "itf { ... on A { name } }") - itf: I - } - - interface I @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name: String - } - - type A implements I @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name: String - } - "#; - - let schema2: &str = r#" - schema - @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) { - query: Query - } - directive @test on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM - directive @join__type(graph: join__Graph!, key: join__FieldSet) repeatable on OBJECT | INTERFACE - directive @join__field(graph: join__Graph, requires: join__FieldSet, provides: join__FieldSet, type: String, external: Boolean, override: String, usedOverridden: Boolean) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION - directive @join__graph(name: String!, url: String!) on ENUM_VALUE - directive @link(url: String, as: String, for: link__Purpose, import: [link__Import]) repeatable on SCHEMA - - scalar join__FieldSet - - scalar link__Import - - enum link__Purpose { - """ - `SECURITY` features provide metadata necessary to securely resolve fields. - """ - SECURITY - - """ - `EXECUTION` features provide metadata necessary for operation execution. - """ - EXECUTION - } - - enum join__Graph { - ACCOUNTS @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev") - INVENTORY @join__graph(name: "inventory", url: "https://inventory.demo.starstuff.dev") - PRODUCTS @join__graph(name: "products", url: "https://products.demo.starstuff.dev") - REVIEWS @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev") - } - - type Query { - me: User - customer: User @test - itf: I - } - - type User @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name: String @test - username: String @join__field(graph:ACCOUNTS, requires: "name") - a: String @join__field(graph:ACCOUNTS, requires: "itf { ... on A { name } }") - itf: I - } - - interface I @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name: String @test - } - - type A implements I @join__type(graph: ACCOUNTS, key: "id") { - id: ID! - name: String @test - } - "#; - let query = "query { me { username } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - - let query = "query { me { a } }"; - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn introspection() { - let schema1: &str = r#" - schema { - query: Query - } - - type Query { - me: User - customer: User - } - - type User { - id: ID - name: String - } - "#; - - let schema2: &str = r#" - schema { - query: Query - } - - type Query { - me: NotUser - } - - - type NotUser { - id: ID! - name: String - } - "#; - - let query = "{ __schema { types { name } } }"; - - assert!(hash(schema1, query).doesnt_match(&hash(schema2, query))); - } - - #[test] - fn fields_with_different_arguments_have_different_hashes() { - let schema: &str = r#" - type Query { - test(arg: Int): String - } - "#; - - let query_one = "query { a: test(arg: 1) b: test(arg: 2) }"; - let query_two = "query { a: test(arg: 1) b: test(arg: 3) }"; - - // This assertion tests an internal hash function that isn't directly - // used for the query hash, and we'll need to make it pass to rely - // solely on the internal function again. - // - // assert!(hash(schema, query_one).doesnt_match(&hash(schema, - // query_two))); - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - } - - #[test] - fn fields_with_different_arguments_on_nest_field_different_hashes() { - let schema: &str = r#" - type Test { - test(arg: Int): String - recursiveLink: Test - } - - type Query { - directLink: Test - } - "#; - - let query_one = "{ directLink { test recursiveLink { test(arg: 1) } } }"; - let query_two = "{ directLink { test recursiveLink { test(arg: 2) } } }"; - - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - assert!(hash(schema, query_one).from_visitor != hash(schema, query_two).from_visitor); - } - - #[test] - fn fields_with_different_aliases_have_different_hashes() { - let schema: &str = r#" - type Query { - test(arg: Int): String - } - "#; - - let query_one = "{ a: test }"; - let query_two = "{ b: test }"; - - // This assertion tests an internal hash function that isn't directly - // used for the query hash, and we'll need to make it pass to rely - // solely on the internal function again. - // - // assert!(hash(schema, query_one).doesnt_match(&hash(schema, query_two))); - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - } - - #[test] - fn operations_with_different_names_have_different_hash() { - let schema: &str = r#" - type Query { - test: String - } - "#; - - let query_one = "query Foo { test }"; - let query_two = "query Bar { test }"; - - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - assert!(hash(schema, query_one).from_visitor != hash(schema, query_two).from_visitor); - } - - #[test] - fn adding_directive_on_operation_changes_hash() { - let schema: &str = r#" - directive @test on QUERY - type Query { - test: String - } - "#; - - let query_one = "query { test }"; - let query_two = "query @test { test }"; - - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - assert!(hash(schema, query_one).from_visitor != hash(schema, query_two).from_visitor); - } - - #[test] - fn order_of_variables_changes_hash() { - let schema: &str = r#" - type Query { - test1(arg: Int): String - test2(arg: Int): String - } - "#; - - let query_one = "query ($foo: Int, $bar: Int) { test1(arg: $foo) test2(arg: $bar) }"; - let query_two = "query ($foo: Int, $bar: Int) { test1(arg: $bar) test2(arg: $foo) }"; - - assert!(hash(schema, query_one).doesnt_match(&hash(schema, query_two))); - } - - #[test] - fn query_variables_with_different_types_have_different_hash() { - let schema: &str = r#" - type Query { - test(arg: Int): String - } - "#; - - let query_one = "query ($var: Int) { test(arg: $var) }"; - let query_two = "query ($var: Int!) { test(arg: $var) }"; - - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - assert!(hash(schema, query_one).from_visitor != hash(schema, query_two).from_visitor); - } - - #[test] - fn query_variables_with_different_default_values_have_different_hash() { - let schema: &str = r#" - type Query { - test(arg: Int): String - } - "#; - - let query_one = "query ($var: Int = 1) { test(arg: $var) }"; - let query_two = "query ($var: Int = 2) { test(arg: $var) }"; - - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - assert!(hash(schema, query_one).from_visitor != hash(schema, query_two).from_visitor); - } - - #[test] - fn adding_directive_to_query_variable_change_hash() { - let schema: &str = r#" - directive @test on VARIABLE_DEFINITION - - type Query { - test(arg: Int): String - } - "#; - - let query_one = "query ($var: Int) { test(arg: $var) }"; - let query_two = "query ($var: Int @test) { test(arg: $var) }"; - - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - assert!(hash(schema, query_one).from_visitor != hash(schema, query_two).from_visitor); - } - - #[test] - fn order_of_directives_change_hash() { - let schema: &str = r#" - directive @foo on FIELD - directive @bar on FIELD - - type Query { - test(arg: Int): String - } - "#; - - let query_one = "{ test @foo @bar }"; - let query_two = "{ test @bar @foo }"; - - assert!(hash(schema, query_one).from_hash_query != hash(schema, query_two).from_hash_query); - assert!(hash(schema, query_one).from_visitor != hash(schema, query_two).from_visitor); - } - - #[test] - fn directive_argument_type_change_hash() { - let schema1: &str = r#" - directive @foo(a: Int) on FIELD - directive @bar on FIELD - - type Query { - test(arg: Int): String - } - "#; - - let schema2: &str = r#" - directive @foo(a: Int!) on FIELD - directive @bar on FIELD - - type Query { - test(arg: Int): String - } - "#; - - let query = "{ test @foo(a: 1) }"; - - assert!(hash(schema1, query).from_hash_query != hash(schema2, query).from_hash_query); - assert!(hash(schema1, query).from_visitor != hash(schema2, query).from_visitor); - } - - #[test] - fn adding_directive_on_schema_changes_hash() { - let schema1: &str = r#" - schema { - query: Query - } - - type Query { - foo: String - } - "#; - - let schema2: &str = r#" - directive @test on SCHEMA - schema @test { - query: Query - } - - type Query { - foo: String - } - "#; - - let query = "{ foo }"; - - assert!(hash(schema1, query).from_hash_query != hash(schema2, query).from_hash_query); - assert!(hash(schema1, query).from_visitor != hash(schema2, query).from_visitor); - } - - #[test] - fn changing_type_of_field_changes_hash() { - let schema1: &str = r#" - type Query { - test: Int - } - "#; - - let schema2: &str = r#" - type Query { - test: Float - } - "#; - - let query = "{ test }"; - - assert!(hash(schema1, query).from_hash_query != hash(schema2, query).from_hash_query); - assert!(hash(schema1, query).from_visitor != hash(schema2, query).from_visitor); - } - - #[test] - fn changing_type_to_interface_changes_hash() { - let schema1: &str = r#" - type Query { - foo: Foo - } - - interface Foo { - value: String - } - "#; - - let schema2: &str = r#" - type Query { - foo: Foo - } - - type Foo { - value: String - } - "#; - - let query = "{ foo { value } }"; - - assert!(hash(schema1, query).from_hash_query != hash(schema2, query).from_hash_query); - assert!(hash(schema1, query).from_visitor != hash(schema2, query).from_visitor); - } - - #[test] - fn changing_operation_kind_changes_hash() { - let schema: &str = r#" - schema { - query: Test - mutation: Test - } - - type Test { - test: String - } - "#; - - let query_one = "query { test }"; - let query_two = "mutation { test }"; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn adding_directive_on_field_should_change_hash() { - let schema: &str = r#" - directive @test on FIELD - - type Query { - test: String - } - "#; - - let query_one = "{ test }"; - let query_two = "{ test @test }"; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn adding_directive_on_fragment_spread_change_hash() { - let schema: &str = r#" - type Query { - test: String - } - "#; - - let query_one = r#" - { ...Test } - - fragment Test on Query { - test - } - "#; - let query_two = r#" - { ...Test @skip(if: false) } - - fragment Test on Query { - test - } - "#; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn adding_directive_on_fragment_change_hash() { - let schema: &str = r#" - directive @test on FRAGMENT_DEFINITION - - type Query { - test: String - } - "#; - - let query_one = r#" - { ...Test } - - fragment Test on Query { - test - } - "#; - let query_two = r#" - { ...Test } - - fragment Test on Query @test { - test - } - "#; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn adding_directive_on_inline_fragment_change_hash() { - let schema: &str = r#" - type Query { - test: String - } - "#; - - let query_one = "{ ... { test } }"; - let query_two = "{ ... @skip(if: false) { test } }"; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn moving_field_changes_hash() { - let schema: &str = r#" - type Query { - me: User - } - - type User { - id: ID - name: String - friend: User - } - "#; - - let query_one = r#" - { - me { - friend { - id - name - } - } - } - "#; - let query_two = r#" - { - me { - friend { - id - } - name - } - } - "#; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn changing_type_of_fragment_changes_hash() { - let schema: &str = r#" - type Query { - fooOrBar: FooOrBar - } - - type Foo { - id: ID - value: String - } - - type Bar { - id: ID - value: String - } - - union FooOrBar = Foo | Bar - "#; - - let query_one = r#" - { - fooOrBar { - ... on Foo { id } - ... on Bar { id } - ... Test - } - } - - fragment Test on Foo { - value - } - "#; - let query_two = r#" - { - fooOrBar { - ... on Foo { id } - ... on Bar { id } - ... Test - } - } - - fragment Test on Bar { - value - } - "#; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn changing_interface_implementors_changes_hash() { - let schema1: &str = r#" - type Query { - data: I - } - - interface I { - id: ID - value: String - } - - type Foo implements I { - id: ID - value: String - foo: String - } - - type Bar { - id: ID - value: String - bar: String - } - "#; - - let schema2: &str = r#" - type Query { - data: I - } - - interface I { - id: ID - value: String - } - - type Foo implements I { - id: ID - value: String - foo2: String - } - - type Bar { - id: ID - value: String - bar: String - } - "#; - - let schema3: &str = r#" - type Query { - data: I - } - - interface I { - id: ID - value: String - } - - type Foo implements I { - id: ID - value: String - foo: String - } - - type Bar implements I { - id: ID - value: String - bar: String - } - "#; - - let query = r#" - { - data { - id - value - } - } - "#; - - // changing an unrelated field in implementors does not change the hash - assert_eq!( - hash(schema1, query).from_hash_query, - hash(schema2, query).from_hash_query - ); - assert_eq!( - hash(schema1, query).from_visitor, - hash(schema2, query).from_visitor - ); - - // adding a new implementor changes the hash - assert_ne!( - hash(schema1, query).from_hash_query, - hash(schema3, query).from_hash_query - ); - assert_ne!( - hash(schema1, query).from_visitor, - hash(schema3, query).from_visitor - ); - } - - #[test] - fn changing_interface_directives_changes_hash() { - let schema1: &str = r#" - directive @a(name: String) on INTERFACE - - type Query { - data: I - } - - interface I @a { - id: ID - value: String - } - - type Foo implements I { - id: ID - value: String - foo: String - } - "#; - - let schema2: &str = r#" - directive @a(name: String) on INTERFACE - - type Query { - data: I - } - - interface I @a(name: "abc") { - id: ID - value: String - } - - type Foo implements I { - id: ID - value: String - foo2: String - } - - "#; - - let query = r#" - { - data { - id - value - } - } - "#; - - // changing a directive applied on the interface definition changes the hash - assert_ne!( - hash(schema1, query).from_hash_query, - hash(schema2, query).from_hash_query - ); - assert_ne!( - hash(schema1, query).from_visitor, - hash(schema2, query).from_visitor - ); - } - - #[test] - fn it_is_weird_so_i_dont_know_how_to_name_it_change_hash() { - let schema: &str = r#" - type Query { - id: ID - someField: SomeType - test: String - } - - type SomeType { - id: ID - test: String - } - "#; - - let query_one = r#" - { - test - someField { id test } - id - } - "#; - let query_two = r#" - { - ...test - someField { id } - } - - fragment test on Query { - id - } - "#; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn it_change_directive_location() { - let schema: &str = r#" - directive @foo on QUERY | VARIABLE_DEFINITION - - type Query { - field(arg: String): String - } - "#; - - let query_one = r#" - query Test ($arg: String @foo) { - field(arg: $arg) - } - "#; - let query_two = r#" - query Test ($arg: String) @foo { - field(arg: $arg) - } - "#; - - assert_ne!( - hash(schema, query_one).from_hash_query, - hash(schema, query_two).from_hash_query - ); - assert_ne!( - hash(schema, query_one).from_visitor, - hash(schema, query_two).from_visitor - ); - } - - #[test] - fn it_changes_on_implementors_list_changes() { - let schema_one: &str = r#" - interface SomeInterface { - value: String - } - - type Foo implements SomeInterface { - value: String - } - - type Bar implements SomeInterface { - value: String - } - - union FooOrBar = Foo | Bar - - type Query { - fooOrBar: FooOrBar - } - "#; - let schema_two: &str = r#" - interface SomeInterface { - value: String - } - - type Foo { - value: String # <= This field shouldn't be a part of query plan anymore - } - - type Bar implements SomeInterface { - value: String - } - - union FooOrBar = Foo | Bar - - type Query { - fooOrBar: FooOrBar - } - "#; - - let query = r#" - { - fooOrBar { - ... on SomeInterface { - value - } - } - } - "#; - - assert_ne!( - hash(schema_one, query).from_hash_query, - hash(schema_two, query).from_hash_query - ); - assert_ne!( - hash(schema_one, query).from_visitor, - hash(schema_two, query).from_visitor - ); - } - - #[test] - fn it_changes_on_context_changes() { - let schema_one: &str = r#" - schema - @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.5", for: EXECUTION) - @link(url: "https://specs.apollo.dev/context/v0.1", for: SECURITY) { - query: Query -} - -directive @context(name: String!) repeatable on INTERFACE | OBJECT | UNION - -directive @context__fromContext(field: String) on ARGUMENT_DEFINITION - -directive @join__directive( - graphs: [join__Graph!] - name: String! - args: join__DirectiveArguments -) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION - -directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE - -directive @join__field( - graph: join__Graph - requires: join__FieldSet - provides: join__FieldSet - type: String - external: Boolean - override: String - usedOverridden: Boolean - overrideLabel: String - contextArguments: [join__ContextArgument!] -) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION - -directive @join__graph(name: String!, url: String!) on ENUM_VALUE - -directive @join__implements( - graph: join__Graph! - interface: String! -) repeatable on OBJECT | INTERFACE - -directive @join__type( - graph: join__Graph! - key: join__FieldSet - extension: Boolean! = false - resolvable: Boolean! = true - isInterfaceObject: Boolean! = false -) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR - -directive @join__unionMember( - graph: join__Graph! - member: String! -) repeatable on UNION - -directive @link( - url: String - as: String - for: link__Purpose - import: [link__Import] -) repeatable on SCHEMA - -scalar context__context - -input join__ContextArgument { - name: String! - type: String! - context: String! - selection: join__FieldValue! -} - -scalar join__DirectiveArguments - -scalar join__FieldSet - -scalar join__FieldValue - -enum join__Graph { - SUBGRAPH1 @join__graph(name: "Subgraph1", url: "https://Subgraph1") - SUBGRAPH2 @join__graph(name: "Subgraph2", url: "https://Subgraph2") -} - -scalar link__Import - -enum link__Purpose { - """ - `SECURITY` features provide metadata necessary to securely resolve fields. - """ - SECURITY - - """ - `EXECUTION` features provide metadata necessary for operation execution. - """ - EXECUTION -} - -type Query @join__type(graph: SUBGRAPH1) { - t: T! @join__field(graph: SUBGRAPH1) -} - - -type T - @join__type(graph: SUBGRAPH1, key: "id") - @context(name: "Subgraph1__context") { - id: ID! - u: U! - uList: [U]! - prop: String! -} - -type U - @join__type(graph: SUBGRAPH1, key: "id") - @join__type(graph: SUBGRAPH2, key: "id") { - id: ID! - b: String! @join__field(graph: SUBGRAPH2) - field: Int! - @join__field( - graph: SUBGRAPH1 - contextArguments: [ - { - context: "Subgraph1__context" - name: "a" - type: "String" - selection: "{ prop }" - } - ] - ) -} - "#; - - // changing T.prop from String! to String - let schema_two: &str = r#" - schema - @link(url: "https://specs.apollo.dev/link/v1.0") - @link(url: "https://specs.apollo.dev/join/v0.5", for: EXECUTION) - @link(url: "https://specs.apollo.dev/context/v0.1", for: SECURITY) { - query: Query -} - -directive @context(name: String!) repeatable on INTERFACE | OBJECT | UNION - -directive @context__fromContext(field: String) on ARGUMENT_DEFINITION - -directive @join__directive( - graphs: [join__Graph!] - name: String! - args: join__DirectiveArguments -) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION - -directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE - -directive @join__field( - graph: join__Graph - requires: join__FieldSet - provides: join__FieldSet - type: String - external: Boolean - override: String - usedOverridden: Boolean - overrideLabel: String - contextArguments: [join__ContextArgument!] -) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION - -directive @join__graph(name: String!, url: String!) on ENUM_VALUE - -directive @join__implements( - graph: join__Graph! - interface: String! -) repeatable on OBJECT | INTERFACE - -directive @join__type( - graph: join__Graph! - key: join__FieldSet - extension: Boolean! = false - resolvable: Boolean! = true - isInterfaceObject: Boolean! = false -) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR - -directive @join__unionMember( - graph: join__Graph! - member: String! -) repeatable on UNION - -directive @link( - url: String - as: String - for: link__Purpose - import: [link__Import] -) repeatable on SCHEMA - -scalar context__context - -input join__ContextArgument { - name: String! - type: String! - context: String! - selection: join__FieldValue! -} - -scalar join__DirectiveArguments - -scalar join__FieldSet - -scalar join__FieldValue - -enum join__Graph { - SUBGRAPH1 @join__graph(name: "Subgraph1", url: "https://Subgraph1") - SUBGRAPH2 @join__graph(name: "Subgraph2", url: "https://Subgraph2") -} - -scalar link__Import - -enum link__Purpose { - """ - `SECURITY` features provide metadata necessary to securely resolve fields. - """ - SECURITY - - """ - `EXECUTION` features provide metadata necessary for operation execution. - """ - EXECUTION -} - -type Query @join__type(graph: SUBGRAPH1) { - t: T! @join__field(graph: SUBGRAPH1) -} - - -type T - @join__type(graph: SUBGRAPH1, key: "id") - @context(name: "Subgraph1__context") { - id: ID! - u: U! - uList: [U]! - prop: String -} - -type U - @join__type(graph: SUBGRAPH1, key: "id") - @join__type(graph: SUBGRAPH2, key: "id") { - id: ID! - b: String! @join__field(graph: SUBGRAPH2) - field: Int! - @join__field( - graph: SUBGRAPH1 - contextArguments: [ - { - context: "Subgraph1__context" - name: "a" - type: "String" - selection: "{ prop }" - } - ] - ) -} - "#; - - let query = r#" - query Query { - t { - __typename - id - u { - __typename - field - } - } - } - "#; - - assert_ne!( - hash(schema_one, query).from_hash_query, - hash(schema_two, query).from_hash_query - ); - assert_ne!( - hash(schema_one, query).from_visitor, - hash(schema_two, query).from_visitor - ); - } -} From 662bb8384e81f7839f58271ec0fe992034465c34 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Tue, 21 Jan 2025 18:06:37 +0200 Subject: [PATCH 23/38] Update cache keys in snapshots --- .../apollo_router__plugins__cache__tests__insert.snap | 5 +++-- .../apollo_router__plugins__cache__tests__no_data.snap | 5 +++-- .../apollo_router__plugins__cache__tests__private.snap | 5 +++-- ..._non_overridden_field_yields_expected_query_plan.snap | 3 ++- ...sts__overridden_field_yields_expected_query_plan.snap | 5 +++-- ...__expose_query_plan__tests__it_expose_query_plan.snap | 9 +++++---- ..._planner__bridge_query_planner__tests__plan_root.snap | 3 ++- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap index a49a81580f..dcbb3496db 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap @@ -1,15 +1,16 @@ --- source: apollo-router/src/plugins/cache/tests.rs expression: cache_keys +snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:ab9056ba140750aa8fe58360172b450fa717e7ea177e4a3c9426fe1291a88da2:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "public" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:0d4d253b049bbea514a54a892902fa4b9b658aedc9b8f2a1308323cdeef3c0ca:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "public" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap index d32bd8453c..9c641d7f3f 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap @@ -1,15 +1,16 @@ --- source: apollo-router/src/plugins/cache/tests.rs expression: cache_keys +snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:4913f52405bb614177e7c718d43da695c2f0e7411707c2f77f1c62380153c8d8:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "[REDACTED]" }, { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:4913f52405bb614177e7c718d43da695c2f0e7411707c2f77f1c62380153c8d8:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "[REDACTED]" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap index 65da6044f9..00d3cf610c 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap @@ -1,15 +1,16 @@ --- source: apollo-router/src/plugins/cache/tests.rs expression: cache_keys +snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:ab9056ba140750aa8fe58360172b450fa717e7ea177e4a3c9426fe1291a88da2:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:0d4d253b049bbea514a54a892902fa4b9b658aedc9b8f2a1308323cdeef3c0ca:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "new", "cache_control": "private" } diff --git a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap index de68830bfe..aad14df151 100644 --- a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap +++ b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap @@ -1,6 +1,7 @@ --- source: apollo-router/src/plugins/progressive_override/tests.rs expression: query_plan +snapshot_kind: text --- { "data": null, @@ -19,7 +20,7 @@ expression: query_plan "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "343157a7d5b7929ebdc0c17cbf0f23c8d3cf0c93a820856d3a189521cc2f24a2", + "schemaAwareHash": "9976b0badd4eda3c5d6a919fd986a679c6e25a33a6b9a8d9a64af6214acf5c3b", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap index 2967a7d6f7..cddd6d02f7 100644 --- a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap +++ b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap @@ -1,6 +1,7 @@ --- source: apollo-router/src/plugins/progressive_override/tests.rs expression: query_plan +snapshot_kind: text --- { "data": { @@ -24,7 +25,7 @@ expression: query_plan "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "df2a0633d70ab97805722bae920647da51b7eb821b06d8a2499683c5c7024316", + "schemaAwareHash": "bacdca1b756776a43ce8c0a522ad47f4efcbb12a60982060d8244b6408f8549f", "authorization": { "is_authenticated": false, "scopes": [], @@ -63,7 +64,7 @@ expression: query_plan "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "56ac7a7cc11b7f293acbdaf0327cb2b676415eab8343e9259322a1609c90455e", + "schemaAwareHash": "4d6b9d9be38f6899559b7b75f3dd53d80b1d81b9e60b51fe7bc49796d2fe9b51", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap index b093e7be08..8c72b7735f 100644 --- a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap +++ b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap @@ -1,6 +1,7 @@ --- source: apollo-router/src/plugins/expose_query_plan.rs expression: "serde_json::to_value(response).unwrap()" +snapshot_kind: text --- { "data": { @@ -69,7 +70,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "45b4beebcbf1df72ab950db7bd278417712b1aa39119317f44ad5b425bdb6997", + "schemaAwareHash": "4454182972c9e14f1a70b967c83413fec5c466e708f1decf6e356b6f3b596fa6", "authorization": { "is_authenticated": false, "scopes": [], @@ -109,7 +110,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "645f3f8763133d2376e33ab3d1145be7ded0ccc8e94e20aba1fbaa34a51633da", + "schemaAwareHash": "54393309c6bee5d5a6b7d8f70862bf10fffe88bb17f4970b878c01625703d774", "authorization": { "is_authenticated": false, "scopes": [], @@ -156,7 +157,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "a79f69245d777abc4afbd7d0a8fc434137fa4fd1079ef082edf4c7746b5a0fcd", + "schemaAwareHash": "455cef144cced4e4ebe26a086102e68fafa8353ff56205aed28f7440f3d1d443", "authorization": { "is_authenticated": false, "scopes": [], @@ -200,7 +201,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5ad94764f288a41312e07745510bf5dade2b63fb82c3d896f7d00408dbbe5cce", + "schemaAwareHash": "6accc51e4e2c72ce715c96d9c33036e0f83391ecd9caf3e78832828b4170054d", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap b/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap index 7b2e0c912f..8129ca79a4 100644 --- a/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap +++ b/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap @@ -1,6 +1,7 @@ --- source: apollo-router/src/query_planner/bridge_query_planner.rs expression: plan.root +snapshot_kind: text --- Fetch( FetchNode { @@ -15,7 +16,7 @@ Fetch( output_rewrites: None, context_rewrites: None, schema_aware_hash: QueryHash( - "65e550250ef331b8dc49d9e2da8f4cd5add979720cbe83ba545a0f78ece8d329", + "89a95c03e0457b9f6158a0f642cc9a8b19b07ec4fead162e1a9b76ccfcb0cb84", ), authorization: CacheKeyMetadata { is_authenticated: false, From 941dad35a76f209a102c43c095e4744a4f805c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 10:58:44 +0100 Subject: [PATCH 24/38] Update some more snapshots --- .../apollo_router__plugins__cache__tests__insert-5.snap | 5 +++-- .../apollo_router__plugins__cache__tests__no_data-3.snap | 5 +++-- .../apollo_router__plugins__cache__tests__private-3.snap | 5 +++-- .../apollo_router__plugins__cache__tests__private-5.snap | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap index ed078770d9..b50b55e579 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap @@ -1,15 +1,16 @@ --- source: apollo-router/src/plugins/cache/tests.rs expression: cache_keys +snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:ab9056ba140750aa8fe58360172b450fa717e7ea177e4a3c9426fe1291a88da2:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "public" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:0d4d253b049bbea514a54a892902fa4b9b658aedc9b8f2a1308323cdeef3c0ca:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "public" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap index fbe291783c..cd3ff3bba7 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap @@ -1,15 +1,16 @@ --- source: apollo-router/src/plugins/cache/tests.rs expression: cache_keys +snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:4913f52405bb614177e7c718d43da695c2f0e7411707c2f77f1c62380153c8d8:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "[REDACTED]" }, { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:4913f52405bb614177e7c718d43da695c2f0e7411707c2f77f1c62380153c8d8:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "[REDACTED]" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap index 76fd27f7fa..31e0baf23e 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap @@ -1,15 +1,16 @@ --- source: apollo-router/src/plugins/cache/tests.rs expression: cache_keys +snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:ab9056ba140750aa8fe58360172b450fa717e7ea177e4a3c9426fe1291a88da2:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:0d4d253b049bbea514a54a892902fa4b9b658aedc9b8f2a1308323cdeef3c0ca:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap index 76fd27f7fa..31e0baf23e 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap @@ -1,15 +1,16 @@ --- source: apollo-router/src/plugins/cache/tests.rs expression: cache_keys +snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:ab9056ba140750aa8fe58360172b450fa717e7ea177e4a3c9426fe1291a88da2:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:0d4d253b049bbea514a54a892902fa4b9b658aedc9b8f2a1308323cdeef3c0ca:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" } From e2afd1a7952bbad7be6ff1982e754da4da2a60b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 11:34:07 +0100 Subject: [PATCH 25/38] Reintroduce operation parsing for query plans loaded from distributed cache --- .../src/query_planner/bridge_query_planner.rs | 2 +- apollo-router/src/query_planner/fetch.rs | 4 +++- apollo-router/src/query_planner/plan.rs | 21 ++++++++++--------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index d843e16f0e..d9b3bada00 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -499,7 +499,7 @@ impl BridgeQueryPlanner { root_node.init_parsed_operations_and_hash_subqueries( &self.subgraph_schemas, &self.schema.raw_sdl, - ); + )?; root_node.extract_authorization_metadata(self.schema.supergraph_schema(), &key); Ok(()) }, diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 84397a191f..a1e1945e2c 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -687,12 +687,14 @@ impl FetchNode { pub(crate) fn init_parsed_operation_and_hash_subquery( &mut self, subgraph_schemas: &SubgraphSchemas, - ) { + ) -> Result<(), ValidationErrors> { let schema = &subgraph_schemas[self.service_name.as_ref()]; + self.operation.init_parsed(&schema.schema)?; self.schema_aware_hash = Arc::new(schema.hash.operation_hash( self.operation.as_serialized(), self.operation_name.as_deref(), )); + Ok(()) } pub(crate) fn extract_authorization_metadata( diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index d93c7bda6c..5d4825875a 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -379,10 +379,10 @@ impl PlanNode { &mut self, subgraph_schemas: &SubgraphSchemas, supergraph_schema_hash: &str, - ) { + ) -> Result<(), ValidationErrors> { match self { PlanNode::Fetch(fetch_node) => { - fetch_node.init_parsed_operation_and_hash_subquery(subgraph_schemas); + fetch_node.init_parsed_operation_and_hash_subquery(subgraph_schemas)?; } PlanNode::Sequence { nodes } => { @@ -390,7 +390,7 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ); + )?; } } PlanNode::Parallel { nodes } => { @@ -398,26 +398,26 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ); + )?; } } PlanNode::Flatten(flatten) => flatten.node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ), + )?, PlanNode::Defer { primary, deferred } => { if let Some(node) = primary.node.as_mut() { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ); + )?; } for deferred_node in deferred { if let Some(node) = &mut deferred_node.node { Arc::make_mut(node).init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ) + )? } } } @@ -426,7 +426,7 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ); + )?; } } PlanNode::Condition { @@ -438,16 +438,17 @@ impl PlanNode { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ); + )?; } if let Some(node) = else_clause.as_mut() { node.init_parsed_operations_and_hash_subqueries( subgraph_schemas, supergraph_schema_hash, - ); + )?; } } } + Ok(()) } #[cfg(test)] From 1997eb145963a4fd200b56ff49cb6cff5a9e2f29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 11:45:44 +0100 Subject: [PATCH 26/38] Hash the raw query hash bytes --- apollo-router/src/plugins/cache/entity.rs | 4 +++- .../apollo_router__plugins__cache__tests__insert-5.snap | 4 ++-- .../apollo_router__plugins__cache__tests__insert.snap | 4 ++-- .../apollo_router__plugins__cache__tests__no_data-3.snap | 4 ++-- .../apollo_router__plugins__cache__tests__no_data.snap | 4 ++-- .../apollo_router__plugins__cache__tests__private-3.snap | 4 ++-- .../apollo_router__plugins__cache__tests__private-5.snap | 4 ++-- .../apollo_router__plugins__cache__tests__private.snap | 4 ++-- ...expose_query_plan__tests__it_expose_query_plan-2.snap | 9 +++++---- apollo-router/src/spec/schema.rs | 5 +++++ 10 files changed, 27 insertions(+), 19 deletions(-) diff --git a/apollo-router/src/plugins/cache/entity.rs b/apollo-router/src/plugins/cache/entity.rs index 3a9fc00d6f..9b19703b0f 100644 --- a/apollo-router/src/plugins/cache/entity.rs +++ b/apollo-router/src/plugins/cache/entity.rs @@ -1220,9 +1220,11 @@ pub(crate) fn hash_vary_headers(headers: &http::HeaderMap) -> String { hex::encode(digest.finalize().as_slice()) } +// XXX(@goto-bus-stop): this doesn't make much sense: QueryHash already includes the operation name. +// This function can be removed outright later at the cost of invalidating all entity caches. pub(crate) fn hash_query(query_hash: &QueryHash, body: &graphql::Request) -> String { let mut digest = Sha256::new(); - digest.update(query_hash.to_string()); + digest.update(query_hash.as_bytes()); digest.update(&[0u8; 1][..]); digest.update(body.operation_name.as_deref().unwrap_or("-").as_bytes()); digest.update(&[0u8; 1][..]); diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap index b50b55e579..6f1a5d9dde 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "public" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "public" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap index dcbb3496db..a5f2c6aa4a 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "public" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "public" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap index cd3ff3bba7..8748400e0f 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "[REDACTED]" }, { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "[REDACTED]" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap index 9c641d7f3f..6d9afef49d 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "[REDACTED]" }, { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0a4841286d62da4754531d0bb3e627cc5455fa8121f59bc0c30334bb08ba5384:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "[REDACTED]" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap index 31e0baf23e..044c4e20a7 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap index 31e0baf23e..044c4e20a7 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap index 00d3cf610c..674b31983f 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:200c9088cd2d6d58a75191c152012e9e6a4651f239adde83368561c543965c03:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:9eb492758fca973e2950fee4fa68dddf24d0847686975455d6ed1d44cc2b5d64:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "new", "cache_control": "private" } diff --git a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap index b093e7be08..8c72b7735f 100644 --- a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap +++ b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap @@ -1,6 +1,7 @@ --- source: apollo-router/src/plugins/expose_query_plan.rs expression: "serde_json::to_value(response).unwrap()" +snapshot_kind: text --- { "data": { @@ -69,7 +70,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "45b4beebcbf1df72ab950db7bd278417712b1aa39119317f44ad5b425bdb6997", + "schemaAwareHash": "4454182972c9e14f1a70b967c83413fec5c466e708f1decf6e356b6f3b596fa6", "authorization": { "is_authenticated": false, "scopes": [], @@ -109,7 +110,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "645f3f8763133d2376e33ab3d1145be7ded0ccc8e94e20aba1fbaa34a51633da", + "schemaAwareHash": "54393309c6bee5d5a6b7d8f70862bf10fffe88bb17f4970b878c01625703d774", "authorization": { "is_authenticated": false, "scopes": [], @@ -156,7 +157,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "a79f69245d777abc4afbd7d0a8fc434137fa4fd1079ef082edf4c7746b5a0fcd", + "schemaAwareHash": "455cef144cced4e4ebe26a086102e68fafa8353ff56205aed28f7440f3d1d443", "authorization": { "is_authenticated": false, "scopes": [], @@ -200,7 +201,7 @@ expression: "serde_json::to_value(response).unwrap()" "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5ad94764f288a41312e07745510bf5dade2b63fb82c3d896f7d00408dbbe5cce", + "schemaAwareHash": "6accc51e4e2c72ce715c96d9c33036e0f83391ecd9caf3e78832828b4170054d", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 50f0ffa715..19f644ab7a 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -444,6 +444,11 @@ impl QueryHash { hasher.update(operation_name.unwrap_or("-")); Self(hasher.finalize().as_slice().into()) } + + /// Return the hash as a byte slice. + pub(crate) fn as_bytes(&self) -> &[u8] { + &self.0 + } } impl std::fmt::Debug for QueryHash { From 5adc7fc8291e314b54832722d9157d8a0bde8baf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 11:54:46 +0100 Subject: [PATCH 27/38] Fix inject_schema_id It's vital that we populate `configuration.apollo` before we try to populate `configuration.apollo.schema_id`. --- apollo-router/src/router_factory.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/apollo-router/src/router_factory.rs b/apollo-router/src/router_factory.rs index 89f0dff729..843f70e284 100644 --- a/apollo-router/src/router_factory.rs +++ b/apollo-router/src/router_factory.rs @@ -740,12 +740,12 @@ pub(crate) async fn create_plugins( } } -fn inject_schema_id(schema_id: &str, configuration: &mut Value) { - if let Some(apollo) = configuration.get_mut("apollo") { - if let Some(apollo) = apollo.as_object_mut() { - apollo.insert("schema_id".to_string(), Value::String(schema_id.to_owned())); - } - } else { +fn inject_schema_id( + // Ideally we'd use &SchemaId, but we'll need to update a bunch of tests to do so + schema_id: &str, + configuration: &mut Value, +) { + if configuration.get("apollo").is_none() { // Warning: this must be done here, otherwise studio reporting will not work if apollo_key().is_some() && apollo_graph_reference().is_some() { if let Some(telemetry) = configuration.as_object_mut() { @@ -755,6 +755,14 @@ fn inject_schema_id(schema_id: &str, configuration: &mut Value) { return; } } + if let Some(apollo) = configuration.get_mut("apollo") { + if let Some(apollo) = apollo.as_object_mut() { + apollo.insert( + "schema_id".to_string(), + Value::String(schema_id.to_string()), + ); + } + } } #[cfg(test)] From 967217ac0ad507e516532e427a382a8101a77cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 12:01:16 +0100 Subject: [PATCH 28/38] Make clippy happy! --- apollo-router/src/batching.rs | 2 +- .../src/query_planner/bridge_query_planner.rs | 5 +-- .../query_planner/caching_query_planner.rs | 4 +- apollo-router/src/query_planner/fetch.rs | 2 +- apollo-router/src/query_planner/plan.rs | 44 +++++-------------- apollo-router/src/query_planner/tests.rs | 4 +- apollo-router/src/spec/schema.rs | 1 + 7 files changed, 20 insertions(+), 42 deletions(-) diff --git a/apollo-router/src/batching.rs b/apollo-router/src/batching.rs index e4283774f4..5eed1bc0a8 100644 --- a/apollo-router/src/batching.rs +++ b/apollo-router/src/batching.rs @@ -485,13 +485,13 @@ mod tests { use crate::graphql; use crate::graphql::Request; use crate::layers::ServiceExt as LayerExt; - use crate::spec::QueryHash; use crate::services::http::HttpClientServiceFactory; use crate::services::router; use crate::services::subgraph; use crate::services::subgraph::SubgraphRequestId; use crate::services::SubgraphRequest; use crate::services::SubgraphResponse; + use crate::spec::QueryHash; use crate::Configuration; use crate::Context; use crate::TestHarness; diff --git a/apollo-router/src/query_planner/bridge_query_planner.rs b/apollo-router/src/query_planner/bridge_query_planner.rs index d9b3bada00..f3dadb816c 100644 --- a/apollo-router/src/query_planner/bridge_query_planner.rs +++ b/apollo-router/src/query_planner/bridge_query_planner.rs @@ -496,10 +496,7 @@ impl BridgeQueryPlanner { operation.clone(), plan_options, |root_node| { - root_node.init_parsed_operations_and_hash_subqueries( - &self.subgraph_schemas, - &self.schema.raw_sdl, - )?; + root_node.init_parsed_operations_and_hash_subqueries(&self.subgraph_schemas)?; root_node.extract_authorization_metadata(self.schema.supergraph_schema(), &key); Ok(()) }, diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index 3093e6414d..0c1ec598b1 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -75,7 +75,9 @@ impl std::fmt::Display for ConfigModeHash { impl std::fmt::Debug for ConfigModeHash { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_tuple("ConfigModeHash").field(&hex::encode(&self.0)).finish() + f.debug_tuple("ConfigModeHash") + .field(&hex::encode(&self.0)) + .finish() } } diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index a1e1945e2c..336c8c77ef 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -687,7 +687,7 @@ impl FetchNode { pub(crate) fn init_parsed_operation_and_hash_subquery( &mut self, subgraph_schemas: &SubgraphSchemas, - ) -> Result<(), ValidationErrors> { + ) -> Result<(), ValidationErrors> { let schema = &subgraph_schemas[self.service_name.as_ref()]; self.operation.init_parsed(&schema.schema)?; self.schema_aware_hash = Arc::new(schema.hash.operation_hash( diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index 5d4825875a..499148b61e 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -378,7 +378,6 @@ impl PlanNode { pub(crate) fn init_parsed_operations_and_hash_subqueries( &mut self, subgraph_schemas: &SubgraphSchemas, - supergraph_schema_hash: &str, ) -> Result<(), ValidationErrors> { match self { PlanNode::Fetch(fetch_node) => { @@ -387,46 +386,31 @@ impl PlanNode { PlanNode::Sequence { nodes } => { for node in nodes { - node.init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )?; + node.init_parsed_operations_and_hash_subqueries(subgraph_schemas)?; } } PlanNode::Parallel { nodes } => { for node in nodes { - node.init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )?; + node.init_parsed_operations_and_hash_subqueries(subgraph_schemas)?; } } - PlanNode::Flatten(flatten) => flatten.node.init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )?, + PlanNode::Flatten(flatten) => flatten + .node + .init_parsed_operations_and_hash_subqueries(subgraph_schemas)?, PlanNode::Defer { primary, deferred } => { if let Some(node) = primary.node.as_mut() { - node.init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )?; + node.init_parsed_operations_and_hash_subqueries(subgraph_schemas)?; } for deferred_node in deferred { if let Some(node) = &mut deferred_node.node { - Arc::make_mut(node).init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )? + Arc::make_mut(node) + .init_parsed_operations_and_hash_subqueries(subgraph_schemas)? } } } PlanNode::Subscription { primary: _, rest } => { if let Some(node) = rest.as_mut() { - node.init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )?; + node.init_parsed_operations_and_hash_subqueries(subgraph_schemas)?; } } PlanNode::Condition { @@ -435,16 +419,10 @@ impl PlanNode { else_clause, } => { if let Some(node) = if_clause.as_mut() { - node.init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )?; + node.init_parsed_operations_and_hash_subqueries(subgraph_schemas)?; } if let Some(node) = else_clause.as_mut() { - node.init_parsed_operations_and_hash_subqueries( - subgraph_schemas, - supergraph_schema_hash, - )?; + node.init_parsed_operations_and_hash_subqueries(subgraph_schemas)?; } } } diff --git a/apollo-router/src/query_planner/tests.rs b/apollo-router/src/query_planner/tests.rs index 8fdd41b674..c22477e38c 100644 --- a/apollo-router/src/query_planner/tests.rs +++ b/apollo-router/src/query_planner/tests.rs @@ -1844,6 +1844,6 @@ fn broken_plan_does_not_panic() { query_planner::fetch::SubgraphSchema::new(subgraph_schema), ); // Run the plan initialization code to make sure it doesn't panic. - let _result = Arc::make_mut(&mut plan.root) - .init_parsed_operations_and_hash_subqueries(&subgraph_schemas, ""); + let _result = + Arc::make_mut(&mut plan.root).init_parsed_operations_and_hash_subqueries(&subgraph_schemas); } diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 19f644ab7a..6bbcb00bb6 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -469,6 +469,7 @@ impl Display for QueryHash { // places. This impl should be deleted outright and we should update usage sites. // If the query hash is truly not required to contain data in those usage sites, we should use // something like an Option instead. +#[allow(clippy::derivable_impls)] // need a place to add that comment ;) impl Default for QueryHash { fn default() -> Self { Self(Default::default()) From 4882b2ab921cf0b44c7e34ad5fcfd62461f2617f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 12:08:13 +0100 Subject: [PATCH 29/38] Snapshot updates for setContext and type conditioned fetching --- .../tests/snapshots/set_context__set_context.snap | 5 +++-- .../set_context__set_context_dependent_fetch_failure.snap | 5 +++-- ...ntext__set_context_dependent_fetch_failure_rust_qp.snap | 5 +++-- .../tests/snapshots/set_context__set_context_list.snap | 5 +++-- .../snapshots/set_context__set_context_list_of_lists.snap | 5 +++-- .../set_context__set_context_list_of_lists_rust_qp.snap | 5 +++-- .../snapshots/set_context__set_context_list_rust_qp.snap | 5 +++-- .../snapshots/set_context__set_context_no_typenames.snap | 5 +++-- .../set_context__set_context_no_typenames_rust_qp.snap | 5 +++-- .../tests/snapshots/set_context__set_context_rust_qp.snap | 5 +++-- .../snapshots/set_context__set_context_type_mismatch.snap | 5 +++-- .../set_context__set_context_type_mismatch_rust_qp.snap | 5 +++-- .../tests/snapshots/set_context__set_context_union.snap | 7 ++++--- .../snapshots/set_context__set_context_union_rust_qp.snap | 7 ++++--- .../set_context__set_context_unrelated_fetch_failure.snap | 7 ++++--- ...ntext__set_context_unrelated_fetch_failure_rust_qp.snap | 7 ++++--- .../snapshots/set_context__set_context_with_null.snap | 5 +++-- .../set_context__set_context_with_null_rust_qp.snap | 5 +++-- .../type_conditions___test_type_conditions_disabled.snap | 5 +++-- .../type_conditions___test_type_conditions_enabled.snap | 7 ++++--- ...t_type_conditions_enabled_generate_query_fragments.snap | 7 ++++--- ...itions___test_type_conditions_enabled_list_of_list.snap | 7 ++++--- ..._test_type_conditions_enabled_list_of_list_of_list.snap | 7 ++++--- ...ype_conditions_enabled_shouldnt_make_article_fetch.snap | 7 ++++--- 24 files changed, 81 insertions(+), 57 deletions(-) diff --git a/apollo-router/tests/snapshots/set_context__set_context.snap b/apollo-router/tests/snapshots/set_context__set_context.snap index 3630f5d86a..1eab8bbe23 100644 --- a/apollo-router/tests/snapshots/set_context__set_context.snap +++ b/apollo-router/tests/snapshots/set_context__set_context.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -34,7 +35,7 @@ expression: response "operationKind": "query", "operationName": "Query__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "b45f75d11c91f90d616e0786fe9a1a675f4f478a6688aa38b9809b3416b66507", + "schemaAwareHash": "93cd64a98952a718e44572d8a89467b74fd38d2197ccb9dbb99f103a8832ac78", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -80,7 +81,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "02dbfc4ce65b1eb8ee39c37f09a88b56ee4671bbcdc935f3ec2a7e25e36c2931", + "schemaAwareHash": "840e47c45ac8cc1e1cb8b787358b62f37eaba7aa3aef89950b863ffcbc2322ec", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap index c0c964b497..160d5cde76 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": null, @@ -43,7 +44,7 @@ expression: response "operationKind": "query", "operationName": "Query_fetch_dependent_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "e8671657b38c13454f18f2bf8df9ebbeb80235c50592f72a2c4141803fe6db59", + "schemaAwareHash": "7594324b57aeffe69ea92380af16f67977a88fa41e0e3bbf9463645b6e835bad", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -89,7 +90,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "8499a69f5ac2e4ce2e0acc76b38b7839b89b6ccba9142494d1a82dd17dd0e5f2", + "schemaAwareHash": "dc7786bb2f22747a1a992a52eb649383d69969eebe70cbd82eb827189279ffa8", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap index 8e555063f8..84a2e52c64 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": null, @@ -43,7 +44,7 @@ expression: response "operationKind": "query", "operationName": "Query_fetch_dependent_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "dfb0f7a17a089f11d0c95f8e9acb3a17fa4fb21216843913bc3a6c62ce2b7fbd", + "schemaAwareHash": "925ceffbd9ad8f4774a2d4bca44148c577123e9676704965c7c11d64d8e17a17", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -89,7 +90,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "f5ae7b50fe8d94eedfb385d91e561de06e3a3256fedca901c0b50ae689b5d630", + "schemaAwareHash": "90cadf96ca5c4f7767f182fff5322ddbf9e079ffb450eac1e4409f95c73eaed6", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list.snap b/apollo-router/tests/snapshots/set_context__set_context_list.snap index fa0a57fc15..6174811657 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -40,7 +41,7 @@ expression: response "operationKind": "query", "operationName": "Query__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "50ba3d7291f38802f222251fe79055e06345e62252e74eba9e01bbec34510cea", + "schemaAwareHash": "7074290ac48917b7125e47b6b7ec1c8671ddcfb73bcedc5fcb2b4536f33b8775", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -86,7 +87,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "02dbfc4ce65b1eb8ee39c37f09a88b56ee4671bbcdc935f3ec2a7e25e36c2931", + "schemaAwareHash": "840e47c45ac8cc1e1cb8b787358b62f37eaba7aa3aef89950b863ffcbc2322ec", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap index 13e0282397..3422ab2cf3 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -44,7 +45,7 @@ expression: response "operationKind": "query", "operationName": "QueryLL__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "589a7dec7f09fdedd06128f1e7396c727740ac1f84ad936ea9c61c3cf96d3ee4", + "schemaAwareHash": "832edda219316a26f9aada0255a90aaba20304abd2f5a3e8e7889e50b5f3fb5f", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -90,7 +91,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "0c966292093d13acca6c8ebb257a146a46840e5a04c9cbaede12e08df98cd489", + "schemaAwareHash": "aa65888282aa780d446889c5aa43c640af03109e1ed45ee5d1b5d3a39adc5253", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap index 6dabc52d4a..9fcdd8fee8 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -44,7 +45,7 @@ expression: response "operationKind": "query", "operationName": "QueryLL__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "560ba34c3cdda6c435aaab55e21528b252f44caabc6c082117e4e9fcc935af5f", + "schemaAwareHash": "bef1a0c245f0cdfdbd937790b843c9ba4b7c2b50d1cb086a5c83c850ab56f4f0", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -90,7 +91,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "b97924736c4f71e4b6e80e2a9e2661130363820bd3df5b2e38000be4a4fb47b5", + "schemaAwareHash": "04010cba840b8718084e60071547cf5a78d2fbffa7b9beeb9131c72695e91c44", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap index 2cee07ad33..1dd170f441 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -40,7 +41,7 @@ expression: response "operationKind": "query", "operationName": "set_context_list_rust_qp__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "f89e82a2730898d4c37766615534224fe8f569b4786a3946e652572a1b99117d", + "schemaAwareHash": "fb6c8621fcf3a325a205c02559f69910d48a6b8da71c62ee2072acfa8093361f", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -86,7 +87,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "57d42b319499942de11c8eaf8bedb3618079a21fb01792b1a0a1ca8a1157d04c", + "schemaAwareHash": "fb9eb384a4ab4d5917306428d3e9017691bfc8e051966453d13e86f0c0b71595", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap b/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap index 0b45046ad7..38973be232 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -32,7 +33,7 @@ expression: response "operationKind": "query", "operationName": "Query__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "b45f75d11c91f90d616e0786fe9a1a675f4f478a6688aa38b9809b3416b66507", + "schemaAwareHash": "93cd64a98952a718e44572d8a89467b74fd38d2197ccb9dbb99f103a8832ac78", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -78,7 +79,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "02dbfc4ce65b1eb8ee39c37f09a88b56ee4671bbcdc935f3ec2a7e25e36c2931", + "schemaAwareHash": "840e47c45ac8cc1e1cb8b787358b62f37eaba7aa3aef89950b863ffcbc2322ec", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap index d110b1b332..9b6bc31221 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -32,7 +33,7 @@ expression: response "operationKind": "query", "operationName": "set_context_no_typenames_rust_qp__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "9b5e7d0de84a6e670d5235682e776eb0ebcd753c955403c7159adea338813a93", + "schemaAwareHash": "30b465d83f1e94c76213a9de0297054a1966908533975406dd18d8db38130b21", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -78,7 +79,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "0b5a9920448d114be6250a0b85f3092f5dfbce80dc89e26880fb28a5ea684d3b", + "schemaAwareHash": "bcfcf2e249fac70efac867eff64799fd5eda2e87c4b426494880acb31cd006e7", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap index 7e7088d73f..217cee17b2 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -34,7 +35,7 @@ expression: response "operationKind": "query", "operationName": "set_context_rust_qp__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "d9094fb75802583731265ab088bd914c2c10ad3d2f7e835cbe13d58811ab797f", + "schemaAwareHash": "ae1c14ec3647fd1aafb1cf9940a17e60d5d52518e537ad31091ca5c0eca8c0ba", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -80,7 +81,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "971f94cb09cb7a1a5564661ae4345da5e709f3ae16b81215db80ae61a740e8d2", + "schemaAwareHash": "6ab83f2051abc6b641bed7e54b923b7e0947a8ce837c2999d1db8a383084eebd", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap index 2c9c27bc14..a2914a5cc2 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -32,7 +33,7 @@ expression: response "operationKind": "query", "operationName": "Query_type_mismatch__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "f47b7620f3ba24d2c15a2978451bd7b59f462e63dc3259a244efe1d971979bfa", + "schemaAwareHash": "9ad83b20b30f763098f5273d5ad3cc9433743714de6ec2096bb03f47cbf99929", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -78,7 +79,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "a6ff3cddbf800b647fdb15f6da6d5e68a71979be93d51852bd289f047202d8ac", + "schemaAwareHash": "d28145b3f482f858ffe3ca1e23c381863e696e164b673041d8cdb145b0c55d40", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap index abacde1e41..3e1fb23b4c 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -32,7 +33,7 @@ expression: response "operationKind": "query", "operationName": "Query_type_mismatch__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "0ca90df94a895d97f403b550a05e72808aee80cbfc6f2f3aea8d32ae0d73d2cd", + "schemaAwareHash": "6ced4663657e945d34ad6a19a38998af7c347843b163a0982cfff305eba08854", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -78,7 +79,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "8ea1a4dce3d934c98814d56884f9e7dad9045562a072216ea903570e01c04680", + "schemaAwareHash": "0adeed095919e474cd2aa64764493eef3aea515cf3b2096c0648fc7828e20c9a", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_union.snap b/apollo-router/tests/snapshots/set_context__set_context_union.snap index 50c3e865df..2cbce9e2eb 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_union.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_union.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -31,7 +32,7 @@ expression: response "operationKind": "query", "operationName": "QueryUnion__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "b6ed60b7e69ed10f45f85aba713969cd99b0e1a832464ba3f225fdf055706424", + "schemaAwareHash": "28832c37359f453e10eba582489c8804e37259da3360561e6001a90794c76e09", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -80,7 +81,7 @@ expression: response "typeCondition": "V" } ], - "schemaAwareHash": "99faa73249f207ea11b1b5064d77f278367398cfee881b2fc3a8a9ebe53f44fe", + "schemaAwareHash": "30ac2f41c830481c78ded59222c0660a17cf960aba864a972ffe6075797c291d", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" @@ -134,7 +135,7 @@ expression: response "typeCondition": "V" } ], - "schemaAwareHash": "e925299b31ea9338d10257fd150ec7ece230f55117105dd631181f4b2a33075a", + "schemaAwareHash": "382811377545b242e2c43d61501a2de89f72f3ffa878fb5dc5692649917d0829", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" diff --git a/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap index c19a7222e8..1a07a4019d 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -31,7 +32,7 @@ expression: response "operationKind": "query", "operationName": "QueryUnion__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "967a248e156212f72f5abb27c01fe3d5e8bb4db154e0f7015db551ee0fe46877", + "schemaAwareHash": "1befcaab6495299098243c1a7fba52f25acefab0bb32fdccc99d4a14c0aa329d", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -80,7 +81,7 @@ expression: response "typeCondition": "V" } ], - "schemaAwareHash": "77647255b7cbdfcb4a47ab2492c0c5252c4f6d06dd4008b104d8770a584a1e32", + "schemaAwareHash": "ead65648c76aeea3b7ebe38aa2a5d9c22c1290f6d16ee358d88b9e10b6b0bfde", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" @@ -133,7 +134,7 @@ expression: response "typeCondition": "V" } ], - "schemaAwareHash": "4a608fbd27c2498c1f31bf737143990d8a2f31e72682542d3169fe2fac6d5834", + "schemaAwareHash": "dd845aa825a1f11609380aede33dde33277439e6f961d1d290f8759872c2657b", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" diff --git a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap index b80bb0c853..92b9baa5d1 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": null, @@ -37,7 +38,7 @@ expression: response "operationKind": "query", "operationName": "Query_fetch_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "d321568b33e32986df6d30a82443ebb919949617ffc33affe8b413658af52b8a", + "schemaAwareHash": "21c1fd295b8f17f7c410715dfdb15e0ed866da5a62d7902e0f21b7e95ff0297f", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -76,7 +77,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "a9aa68bb30f2040298629fc2fe72dc8438ce16bcdfdbe1a16ff088cf61d38719", + "schemaAwareHash": "6721561884babef3ac12e05eb2038d2e810bff3c310a23b1b2d956652ac13b89", "serviceName": "Subgraph2", "variableUsages": [] }, @@ -128,7 +129,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "da0e31f9990723a68dbd1e1bb164a068342da5561db1a28679693a406429d09a", + "schemaAwareHash": "68db542f979e4f469a4286fade8e69d933ec57b71e8d5bcfcbe503d4c86c5add", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap index 77341c5367..3b2838a0cb 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": null, @@ -37,7 +38,7 @@ expression: response "operationKind": "query", "operationName": "Query_fetch_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "03786f26d73a1ad1bfa3fed40f657316857018dc1105b2da578904373b7e1882", + "schemaAwareHash": "9305e1c92eb20ac4467958e1003356b22f2f3537a50cc7745c3c9958add885d9", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -86,7 +87,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "f615a413abdf99efaf7e760e1246371aa5dd0f2330820cf295335ed48cc077ed", + "schemaAwareHash": "8d4ddefb8baec1535ec6d10d4ec1db38bd0cb05933efab7d7097f069867e7e30", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" @@ -129,7 +130,7 @@ expression: response "typeCondition": "U" } ], - "schemaAwareHash": "0e71b293b5c0b6143252865b2c97338cd72a558897b0a478dd0cd8b027f9a5a3", + "schemaAwareHash": "9bf77af5fd96f9da379241494705d6d5a1c41929975f4dffd83596c5351141c9", "serviceName": "Subgraph2", "variableUsages": [] }, diff --git a/apollo-router/tests/snapshots/set_context__set_context_with_null.snap b/apollo-router/tests/snapshots/set_context__set_context_with_null.snap index f4c5eb3898..3ee08bb57c 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_with_null.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_with_null.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -29,7 +30,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "73819a48542fc2a3eb3a831b27ab5cc0b1286a73c2750279d8886fc529ba9e9e", + "schemaAwareHash": "e6208acfdfd0841365a3b63a8fcff118daf4ebdffce940c1e951abe6f0e551c4", "authorization": { "is_authenticated": false, "scopes": [], @@ -82,7 +83,7 @@ expression: response "renameKeyTo": "contextualArgument_1_0" } ], - "schemaAwareHash": "042955e454618e67e75f3c86c9b8c71e2da866f1c40d0dc462d52053e1861803", + "schemaAwareHash": "42e5f12379b7136efe99706e8569cf56618742fbf4cef43fa44347e441b6a04d", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap index fcd539eeb1..3c2696a780 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/set_context.rs expression: response +snapshot_kind: text --- { "data": { @@ -29,7 +30,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5a33cc9574d930882310fe1f9ddae8f262a448a50ac9a899e71896a339fa0f85", + "schemaAwareHash": "18757152409a0e2ea274a9cffe092fcb8c85a1e85d030d1d3528ceecbb9e1c5d", "authorization": { "is_authenticated": false, "scopes": [], @@ -81,7 +82,7 @@ expression: response "renameKeyTo": "contextualArgument_1_0" } ], - "schemaAwareHash": "4f6eeca0e601bbf183b759aa785df84eb0c435a266a36568238e8d721dc8fc3c", + "schemaAwareHash": "913186d70ede74717b3ceb17f38dda8a39e8a8c2eefb903b18ecce8c0c6e98ce", "authorization": { "is_authenticated": false, "scopes": [], 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 de7f4d2827..dcb16c501e 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -79,7 +80,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "18631e67bb0c6b514cb51e8dff155a2900c8000ad319ea4784e5ca8b1275aca2", + "schemaAwareHash": "ad3dd3ed27be8f5048e968c8295aafc42587e6dafc501a690c4ce0ee5d03e2d2", "authorization": { "is_authenticated": false, "scopes": [], @@ -137,7 +138,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7f3ec4c2c644d43e54d95da83790166d87ab6bfcb31fe5692d8262199bff6d3f", + "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", "authorization": { "is_authenticated": false, "scopes": [], 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 39b73eabbc..0f96dd030c 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -79,7 +80,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "18631e67bb0c6b514cb51e8dff155a2900c8000ad319ea4784e5ca8b1275aca2", + "schemaAwareHash": "ad3dd3ed27be8f5048e968c8295aafc42587e6dafc501a690c4ce0ee5d03e2d2", "authorization": { "is_authenticated": false, "scopes": [], @@ -141,7 +142,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7f3ec4c2c644d43e54d95da83790166d87ab6bfcb31fe5692d8262199bff6d3f", + "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", "authorization": { "is_authenticated": false, "scopes": [], @@ -201,7 +202,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3874fd9db4a0302422701b93506f42a5de5604355be7093fa2abe23f440161f9", + "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap index 39b73eabbc..0f96dd030c 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -79,7 +80,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "18631e67bb0c6b514cb51e8dff155a2900c8000ad319ea4784e5ca8b1275aca2", + "schemaAwareHash": "ad3dd3ed27be8f5048e968c8295aafc42587e6dafc501a690c4ce0ee5d03e2d2", "authorization": { "is_authenticated": false, "scopes": [], @@ -141,7 +142,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7f3ec4c2c644d43e54d95da83790166d87ab6bfcb31fe5692d8262199bff6d3f", + "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", "authorization": { "is_authenticated": false, "scopes": [], @@ -201,7 +202,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3874fd9db4a0302422701b93506f42a5de5604355be7093fa2abe23f440161f9", + "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", "authorization": { "is_authenticated": false, "scopes": [], 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 ec86110080..3d5668e6c6 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -141,7 +142,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "65c1648beef44b81ac988224191b18ff469c641fd33032ef0c84165245018b62", + "schemaAwareHash": "ae9c32852d8a2f9e0fec54ade465709b59218cd64b7e7c551d0df3e1c1be43e0", "authorization": { "is_authenticated": false, "scopes": [], @@ -204,7 +205,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7f3ec4c2c644d43e54d95da83790166d87ab6bfcb31fe5692d8262199bff6d3f", + "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", "authorization": { "is_authenticated": false, "scopes": [], @@ -265,7 +266,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3874fd9db4a0302422701b93506f42a5de5604355be7093fa2abe23f440161f9", + "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", "authorization": { "is_authenticated": false, "scopes": [], 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 e4ba5927a3..b8363c3f85 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -145,7 +146,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "f2466229a91f69cadfa844a20343b03668b7f85fd1310a4b20ba9382ffa2f5e7", + "schemaAwareHash": "76dee51cf4c0515d390c58da3fd7a084589834f8cbe9f96dc725f0b344fb4f98", "authorization": { "is_authenticated": false, "scopes": [], @@ -209,7 +210,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "7f3ec4c2c644d43e54d95da83790166d87ab6bfcb31fe5692d8262199bff6d3f", + "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", "authorization": { "is_authenticated": false, "scopes": [], @@ -271,7 +272,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3874fd9db4a0302422701b93506f42a5de5604355be7093fa2abe23f440161f9", + "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap index 8ae0b59f67..30a3af074e 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -54,7 +55,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "cc52bb826d3c06b3ccbc421340fe3f49a81dc2b71dcb6a931a9a769745038e3f", + "schemaAwareHash": "c9b833d9f2b0b0c67a58c9c69893584f46f8c9e8185b745aa69edf1b48698489", "authorization": { "is_authenticated": false, "scopes": [], @@ -116,7 +117,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6e83e0a67b509381f1a0c2dfe84db92d0dd6bf4bb23fe4c97ccd3d871364c9f4", + "schemaAwareHash": "ba9e1b441ac7bc2cfbc633e58ef2302635a247dd9e97cc24f027c5334d22966d", "authorization": { "is_authenticated": false, "scopes": [], @@ -176,7 +177,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "67834874c123139d942b140fb9ff00ed4e22df25228c3e758eeb44b28d3847eb", + "schemaAwareHash": "c66770a56203e72289af611bc6bde0ffe0248d8b63db2a63d94e4e889e888116", "authorization": { "is_authenticated": false, "scopes": [], From 2c4d3713d3742d624f4a39aadff292bba8c02b9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 12:15:47 +0100 Subject: [PATCH 30/38] Update remaining snapshots --- .../type_conditions___test_type_conditions_disabled-2.snap | 5 +++-- .../type_conditions___test_type_conditions_enabled-2.snap | 7 ++++--- ...type_conditions_enabled_generate_query_fragments-2.snap | 7 ++++--- ...ions___test_type_conditions_enabled_list_of_list-2.snap | 7 ++++--- ...est_type_conditions_enabled_list_of_list_of_list-2.snap | 7 ++++--- ...e_conditions_enabled_shouldnt_make_article_fetch-2.snap | 7 ++++--- 6 files changed, 23 insertions(+), 17 deletions(-) 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 4d61ae95b4..32e8231395 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -79,7 +80,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "1d2d8b1ab80b4b1293e9753a915997835e6ff5bc54ba4c9b400abe7fa4661386", + "schemaAwareHash": "5e7085d44036286e5fca029a1f3fd6be1791fa1665597bff009141ee370ee279", "authorization": { "is_authenticated": false, "scopes": [], @@ -137,7 +138,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "66a2bd39c499f1edd8c3ec1bfbc170cb995c6f9e23427b5486b633decd2da08b", + "schemaAwareHash": "e386fd2fcbd895c94bae09682c354184e8081225d524060f54ab69d3bca8cf02", "authorization": { "is_authenticated": false, "scopes": [], 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 c89cab9c7d..62938baac1 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -79,7 +80,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "1d2d8b1ab80b4b1293e9753a915997835e6ff5bc54ba4c9b400abe7fa4661386", + "schemaAwareHash": "5e7085d44036286e5fca029a1f3fd6be1791fa1665597bff009141ee370ee279", "authorization": { "is_authenticated": false, "scopes": [], @@ -140,7 +141,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "31465e7b7e358ea9407067188249b51fd7342088e6084360ed0df28199cef5cc", + "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", "authorization": { "is_authenticated": false, "scopes": [], @@ -199,7 +200,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "550ad525da9bb9497fb0d51bf7a64b7d5d73ade5ee7d2e425573dc7e2e248e99", + "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap index c89cab9c7d..62938baac1 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -79,7 +80,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "1d2d8b1ab80b4b1293e9753a915997835e6ff5bc54ba4c9b400abe7fa4661386", + "schemaAwareHash": "5e7085d44036286e5fca029a1f3fd6be1791fa1665597bff009141ee370ee279", "authorization": { "is_authenticated": false, "scopes": [], @@ -140,7 +141,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "31465e7b7e358ea9407067188249b51fd7342088e6084360ed0df28199cef5cc", + "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", "authorization": { "is_authenticated": false, "scopes": [], @@ -199,7 +200,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "550ad525da9bb9497fb0d51bf7a64b7d5d73ade5ee7d2e425573dc7e2e248e99", + "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", "authorization": { "is_authenticated": false, "scopes": [], 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 371fd3496e..757fdd9556 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -141,7 +142,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "b74616ae898acf3abefb83e24bde5faf0de0f9475d703b105b60c18c7372ab13", + "schemaAwareHash": "9191ecc2fda635c0dde0e40b3656760f28a5da08198b3512764c3172d5783856", "authorization": { "is_authenticated": false, "scopes": [], @@ -203,7 +204,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "31465e7b7e358ea9407067188249b51fd7342088e6084360ed0df28199cef5cc", + "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", "authorization": { "is_authenticated": false, "scopes": [], @@ -263,7 +264,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "550ad525da9bb9497fb0d51bf7a64b7d5d73ade5ee7d2e425573dc7e2e248e99", + "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", "authorization": { "is_authenticated": false, "scopes": [], 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 354bd034a9..2f8650485e 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 @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -145,7 +146,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "dc1df8e8d701876c6ea7d25bbeab92a5629a82e55660ccc48fc37e12d5157efa", + "schemaAwareHash": "3db19df4fd1b36e4ed279e01e3a31cb0843e8f9dfdb9876bfcd09cf223f27aa3", "authorization": { "is_authenticated": false, "scopes": [], @@ -208,7 +209,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "31465e7b7e358ea9407067188249b51fd7342088e6084360ed0df28199cef5cc", + "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", "authorization": { "is_authenticated": false, "scopes": [], @@ -269,7 +270,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "550ad525da9bb9497fb0d51bf7a64b7d5d73ade5ee7d2e425573dc7e2e248e99", + "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap index 8811454f74..86303e3a96 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/type_conditions.rs expression: response +snapshot_kind: text --- { "data": { @@ -54,7 +55,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "446c1a72168f736a89e4f56799333e05b26092d36fc55e22c2e92828061c787b", + "schemaAwareHash": "434b300a2320dc017f003077aa17171613350baaa806426e88d724d1a5c01600", "authorization": { "is_authenticated": false, "scopes": [], @@ -115,7 +116,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "f9052a9ce97a084006a1f2054b7e0fba8734f24bb53cf0f7e0ba573c7e709b98", + "schemaAwareHash": "5fc15a41a51385410e8fc992c29f3dfb9db55c82c9cb6f63519d2954a119355a", "authorization": { "is_authenticated": false, "scopes": [], @@ -174,7 +175,7 @@ expression: response "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "027cac0584184439636aea68757da18f3e0e18142948e3b8625724f93e8720fc", + "schemaAwareHash": "f571d05338d7b212a3a98e5e685ae3f69cad5a512af1004ebcc3cef772ba6dd2", "authorization": { "is_authenticated": false, "scopes": [], From 671e2da627f1b523ebb11f02b85405d7b33f6256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 12:50:07 +0100 Subject: [PATCH 31/38] Use a subgraph serialization without indentation for hashing --- .../apollo_router__plugins__cache__tests__insert-5.snap | 4 ++-- .../apollo_router__plugins__cache__tests__insert.snap | 4 ++-- .../apollo_router__plugins__cache__tests__no_data-3.snap | 4 ++-- .../apollo_router__plugins__cache__tests__no_data.snap | 4 ++-- .../apollo_router__plugins__cache__tests__private-3.snap | 4 ++-- .../apollo_router__plugins__cache__tests__private-5.snap | 4 ++-- .../apollo_router__plugins__cache__tests__private.snap | 4 ++-- ...__non_overridden_field_yields_expected_query_plan.snap | 2 +- ...ests__overridden_field_yields_expected_query_plan.snap | 4 ++-- ..._expose_query_plan__tests__it_expose_query_plan-2.snap | 8 ++++---- ...s__expose_query_plan__tests__it_expose_query_plan.snap | 8 ++++---- apollo-router/src/query_planner/fetch.rs | 2 +- ...y_planner__bridge_query_planner__tests__plan_root.snap | 2 +- .../tests/snapshots/set_context__set_context.snap | 4 ++-- .../set_context__set_context_dependent_fetch_failure.snap | 4 ++-- ...text__set_context_dependent_fetch_failure_rust_qp.snap | 4 ++-- .../tests/snapshots/set_context__set_context_list.snap | 4 ++-- .../snapshots/set_context__set_context_list_of_lists.snap | 4 ++-- .../set_context__set_context_list_of_lists_rust_qp.snap | 4 ++-- .../snapshots/set_context__set_context_list_rust_qp.snap | 4 ++-- .../snapshots/set_context__set_context_no_typenames.snap | 4 ++-- .../set_context__set_context_no_typenames_rust_qp.snap | 4 ++-- .../tests/snapshots/set_context__set_context_rust_qp.snap | 4 ++-- .../snapshots/set_context__set_context_type_mismatch.snap | 4 ++-- .../set_context__set_context_type_mismatch_rust_qp.snap | 4 ++-- .../tests/snapshots/set_context__set_context_union.snap | 6 +++--- .../snapshots/set_context__set_context_union_rust_qp.snap | 6 +++--- .../set_context__set_context_unrelated_fetch_failure.snap | 6 +++--- ...text__set_context_unrelated_fetch_failure_rust_qp.snap | 6 +++--- .../snapshots/set_context__set_context_with_null.snap | 4 ++-- .../set_context__set_context_with_null_rust_qp.snap | 4 ++-- ...type_conditions___test_type_conditions_disabled-2.snap | 4 ++-- .../type_conditions___test_type_conditions_disabled.snap | 4 ++-- .../type_conditions___test_type_conditions_enabled-2.snap | 6 +++--- .../type_conditions___test_type_conditions_enabled.snap | 6 +++--- ...ype_conditions_enabled_generate_query_fragments-2.snap | 6 +++--- ..._type_conditions_enabled_generate_query_fragments.snap | 6 +++--- ...ons___test_type_conditions_enabled_list_of_list-2.snap | 6 +++--- ...tions___test_type_conditions_enabled_list_of_list.snap | 6 +++--- ...st_type_conditions_enabled_list_of_list_of_list-2.snap | 6 +++--- ...test_type_conditions_enabled_list_of_list_of_list.snap | 6 +++--- ..._conditions_enabled_shouldnt_make_article_fetch-2.snap | 6 +++--- ...pe_conditions_enabled_shouldnt_make_article_fetch.snap | 6 +++--- 43 files changed, 101 insertions(+), 101 deletions(-) diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap index 6f1a5d9dde..8734f2dbc1 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert-5.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:e734548bbe559d607f045e8fe5b5225543a1093dac991e137d1208a12af536de:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "public" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:user:type:Query:hash:3e689b15c9cee1f2812c319a66ddbe8bfc452c8ab6759566ed1987cae95178cd:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "public" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap index a5f2c6aa4a..5f8ca305d8 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__insert.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:e734548bbe559d607f045e8fe5b5225543a1093dac991e137d1208a12af536de:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "public" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:user:type:Query:hash:3e689b15c9cee1f2812c319a66ddbe8bfc452c8ab6759566ed1987cae95178cd:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "public" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap index 8748400e0f..dcb3aff923 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data-3.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:5f460b74668616b2388b1afed7af6557ee4a0d60fbca18f3b4c59b8027035f32:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "[REDACTED]" }, { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:5f460b74668616b2388b1afed7af6557ee4a0d60fbca18f3b4c59b8027035f32:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "cached", "cache_control": "[REDACTED]" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap index 6d9afef49d..3f36da3436 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__no_data.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5221ff42b311b757445c096c023cee4fefab5de49735e421c494f1119326317b:hash:5f460b74668616b2388b1afed7af6557ee4a0d60fbca18f3b4c59b8027035f32:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "[REDACTED]" }, { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:0f025a646643e360691e6ea43b7b62a4799ea110a624ae65a32cb08de47f4b33:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:5f460b74668616b2388b1afed7af6557ee4a0d60fbca18f3b4c59b8027035f32:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "[REDACTED]" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap index 044c4e20a7..0a2452b735 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-3.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:e734548bbe559d607f045e8fe5b5225543a1093dac991e137d1208a12af536de:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:3e689b15c9cee1f2812c319a66ddbe8bfc452c8ab6759566ed1987cae95178cd:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap index 044c4e20a7..0a2452b735 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private-5.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:e734548bbe559d607f045e8fe5b5225543a1093dac991e137d1208a12af536de:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:3e689b15c9cee1f2812c319a66ddbe8bfc452c8ab6759566ed1987cae95178cd:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "cached", "cache_control": "private" } diff --git a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap index 674b31983f..ec2044d719 100644 --- a/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap +++ b/apollo-router/src/plugins/cache/snapshots/apollo_router__plugins__cache__tests__private.snap @@ -5,12 +5,12 @@ snapshot_kind: text --- [ { - "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:274ea7d70a6962f0388f190ff0e165d46f9daf74d41b0385455f296c18ed3c66:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", + "key": "version:1.0:subgraph:orga:type:Organization:entity:5811967f540d300d249ab30ae681359a7815fdb5d3dc71a94be1d491006a6b27:hash:e734548bbe559d607f045e8fe5b5225543a1093dac991e137d1208a12af536de:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c", "status": "new", "cache_control": "private" }, { - "key": "version:1.0:subgraph:user:type:Query:hash:97e46148fc7415e5341ba63f8023cae426de3df9d176ab0d87f7c68a401134ea:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", + "key": "version:1.0:subgraph:user:type:Query:hash:3e689b15c9cee1f2812c319a66ddbe8bfc452c8ab6759566ed1987cae95178cd:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c:03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", "status": "new", "cache_control": "private" } diff --git a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap index aad14df151..fd19a91eb7 100644 --- a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap +++ b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__non_overridden_field_yields_expected_query_plan.snap @@ -20,7 +20,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "9976b0badd4eda3c5d6a919fd986a679c6e25a33a6b9a8d9a64af6214acf5c3b", + "schemaAwareHash": "83a61d8e05a2342e4c13c5b518e1e4a5b4cbc405477fce069c784526eb3b1ae5", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap index cddd6d02f7..a12803669a 100644 --- a/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap +++ b/apollo-router/src/plugins/progressive_override/snapshots/apollo_router__plugins__progressive_override__tests__overridden_field_yields_expected_query_plan.snap @@ -25,7 +25,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "bacdca1b756776a43ce8c0a522ad47f4efcbb12a60982060d8244b6408f8549f", + "schemaAwareHash": "3c438d69bd20986101e4fb91167d5db4b871b250a5e5b670e19e9305b2756baa", "authorization": { "is_authenticated": false, "scopes": [], @@ -64,7 +64,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "4d6b9d9be38f6899559b7b75f3dd53d80b1d81b9e60b51fe7bc49796d2fe9b51", + "schemaAwareHash": "fcec2495ee805f82a5712f74f89797ed678eb5118ff8044a1c8fb232d6dd16df", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap index 8c72b7735f..cb80da3c18 100644 --- a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap +++ b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan-2.snap @@ -70,7 +70,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "4454182972c9e14f1a70b967c83413fec5c466e708f1decf6e356b6f3b596fa6", + "schemaAwareHash": "5c4bde1b693a9d93618856d221a620783601d3e6141991ea1d49763dca5fe94b", "authorization": { "is_authenticated": false, "scopes": [], @@ -110,7 +110,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "54393309c6bee5d5a6b7d8f70862bf10fffe88bb17f4970b878c01625703d774", + "schemaAwareHash": "1763ef26b5543dd364a96f6b29f9db6edbbe06ef4b260fd6dd59258cf09134b8", "authorization": { "is_authenticated": false, "scopes": [], @@ -157,7 +157,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "455cef144cced4e4ebe26a086102e68fafa8353ff56205aed28f7440f3d1d443", + "schemaAwareHash": "b634e94c76926292e24ea336046389758058cccf227b49917b625adccfc29d07", "authorization": { "is_authenticated": false, "scopes": [], @@ -201,7 +201,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6accc51e4e2c72ce715c96d9c33036e0f83391ecd9caf3e78832828b4170054d", + "schemaAwareHash": "2ff7e653609dee610e4c5e06a666391889af36a0f78ce44a15cf758e4cc897e5", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap index 8c72b7735f..cb80da3c18 100644 --- a/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap +++ b/apollo-router/src/plugins/snapshots/apollo_router__plugins__expose_query_plan__tests__it_expose_query_plan.snap @@ -70,7 +70,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "4454182972c9e14f1a70b967c83413fec5c466e708f1decf6e356b6f3b596fa6", + "schemaAwareHash": "5c4bde1b693a9d93618856d221a620783601d3e6141991ea1d49763dca5fe94b", "authorization": { "is_authenticated": false, "scopes": [], @@ -110,7 +110,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "54393309c6bee5d5a6b7d8f70862bf10fffe88bb17f4970b878c01625703d774", + "schemaAwareHash": "1763ef26b5543dd364a96f6b29f9db6edbbe06ef4b260fd6dd59258cf09134b8", "authorization": { "is_authenticated": false, "scopes": [], @@ -157,7 +157,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "455cef144cced4e4ebe26a086102e68fafa8353ff56205aed28f7440f3d1d443", + "schemaAwareHash": "b634e94c76926292e24ea336046389758058cccf227b49917b625adccfc29d07", "authorization": { "is_authenticated": false, "scopes": [], @@ -201,7 +201,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6accc51e4e2c72ce715c96d9c33036e0f83391ecd9caf3e78832828b4170054d", + "schemaAwareHash": "2ff7e653609dee610e4c5e06a666391889af36a0f78ce44a15cf758e4cc897e5", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 336c8c77ef..495132220a 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -104,7 +104,7 @@ pub(crate) struct SubgraphSchema { impl SubgraphSchema { pub(crate) fn new(schema: Valid) -> Self { - let sdl = schema.to_string(); + let sdl = schema.serialize().no_indent().to_string(); Self { schema: Arc::new(schema), hash: Arc::new(SchemaId::new(&sdl)), diff --git a/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap b/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap index 8129ca79a4..caa522cc71 100644 --- a/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap +++ b/apollo-router/src/query_planner/snapshots/apollo_router__query_planner__bridge_query_planner__tests__plan_root.snap @@ -16,7 +16,7 @@ Fetch( output_rewrites: None, context_rewrites: None, schema_aware_hash: QueryHash( - "89a95c03e0457b9f6158a0f642cc9a8b19b07ec4fead162e1a9b76ccfcb0cb84", + "771df7db7de827ae96394500bf9386e0a85e95a960a196f9aad5e2052b0415e7", ), authorization: CacheKeyMetadata { is_authenticated: false, diff --git a/apollo-router/tests/snapshots/set_context__set_context.snap b/apollo-router/tests/snapshots/set_context__set_context.snap index 1eab8bbe23..264f37cdb6 100644 --- a/apollo-router/tests/snapshots/set_context__set_context.snap +++ b/apollo-router/tests/snapshots/set_context__set_context.snap @@ -35,7 +35,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "93cd64a98952a718e44572d8a89467b74fd38d2197ccb9dbb99f103a8832ac78", + "schemaAwareHash": "c36f4148cc7bdd9d001316592ffaa2c0079f93586fb1ca110aa5107262afdb44", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -81,7 +81,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "840e47c45ac8cc1e1cb8b787358b62f37eaba7aa3aef89950b863ffcbc2322ec", + "schemaAwareHash": "6d7e81f6b6fb544929a7f5fbc9123b6a5ad49687dbd4528d2c5b91d0706ded2f", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap index 160d5cde76..92771a71ae 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure.snap @@ -44,7 +44,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query_fetch_dependent_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "7594324b57aeffe69ea92380af16f67977a88fa41e0e3bbf9463645b6e835bad", + "schemaAwareHash": "d93d363a607457b0fab08dcc177dadd9f647e2ce2c0e893017c99b9e0a452d15", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -90,7 +90,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "dc7786bb2f22747a1a992a52eb649383d69969eebe70cbd82eb827189279ffa8", + "schemaAwareHash": "1e00dfec6c7e1f482d9615cc2d530e79d2503f8527e2f3ee60a1b5b462088d5d", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap index 84a2e52c64..8921d12e90 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_dependent_fetch_failure_rust_qp.snap @@ -44,7 +44,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query_fetch_dependent_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "925ceffbd9ad8f4774a2d4bca44148c577123e9676704965c7c11d64d8e17a17", + "schemaAwareHash": "f4657a18062d1238f3b2c70313ccc4033382f1ab564bdb17e9c23b4f301502eb", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -90,7 +90,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "90cadf96ca5c4f7767f182fff5322ddbf9e079ffb450eac1e4409f95c73eaed6", + "schemaAwareHash": "a474ca499374743ca5ecf861b75aa195796cf573af48a7f948f8652fecb38981", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list.snap b/apollo-router/tests/snapshots/set_context__set_context_list.snap index 6174811657..d1111153fb 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list.snap @@ -41,7 +41,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "7074290ac48917b7125e47b6b7ec1c8671ddcfb73bcedc5fcb2b4536f33b8775", + "schemaAwareHash": "fae8d004c9012c52e0eaf36b650afe513a58164f3b7c6721a92194dc2594e222", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -87,7 +87,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "840e47c45ac8cc1e1cb8b787358b62f37eaba7aa3aef89950b863ffcbc2322ec", + "schemaAwareHash": "6d7e81f6b6fb544929a7f5fbc9123b6a5ad49687dbd4528d2c5b91d0706ded2f", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap index 3422ab2cf3..e089bf37c3 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists.snap @@ -45,7 +45,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "QueryLL__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "832edda219316a26f9aada0255a90aaba20304abd2f5a3e8e7889e50b5f3fb5f", + "schemaAwareHash": "1623e5c5abcc506f378e168da719f9163a03ee62feba9413b5664c8d6b5f1b37", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -91,7 +91,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "aa65888282aa780d446889c5aa43c640af03109e1ed45ee5d1b5d3a39adc5253", + "schemaAwareHash": "9f32284e712d75def9f4f7d28f563ff31101b9e6492cef5158b9b10b3a389cd2", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap index 9fcdd8fee8..ca3c9030bd 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list_of_lists_rust_qp.snap @@ -45,7 +45,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "QueryLL__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "bef1a0c245f0cdfdbd937790b843c9ba4b7c2b50d1cb086a5c83c850ab56f4f0", + "schemaAwareHash": "faf129da6ef159312229575dba91b32e5218486fbb568126314cadeaab16dfff", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -91,7 +91,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "04010cba840b8718084e60071547cf5a78d2fbffa7b9beeb9131c72695e91c44", + "schemaAwareHash": "23d14a2cd64a8ae9af87935761752a6b6e54e376bc5bcad977c8d8bc7fae0569", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap index 1dd170f441..8dd2359bb9 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_list_rust_qp.snap @@ -41,7 +41,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "set_context_list_rust_qp__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "fb6c8621fcf3a325a205c02559f69910d48a6b8da71c62ee2072acfa8093361f", + "schemaAwareHash": "4acf5d3b86cc26a35aec8502ed93a957743d2f614f0b2c2af410caddb7a5a1d7", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -87,7 +87,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "fb9eb384a4ab4d5917306428d3e9017691bfc8e051966453d13e86f0c0b71595", + "schemaAwareHash": "d5b8a4e67c6af63de00246c793278373735149a7f92b9b9b85fdf640e046af75", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap b/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap index 38973be232..40018ffb66 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_no_typenames.snap @@ -33,7 +33,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "93cd64a98952a718e44572d8a89467b74fd38d2197ccb9dbb99f103a8832ac78", + "schemaAwareHash": "c36f4148cc7bdd9d001316592ffaa2c0079f93586fb1ca110aa5107262afdb44", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -79,7 +79,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "840e47c45ac8cc1e1cb8b787358b62f37eaba7aa3aef89950b863ffcbc2322ec", + "schemaAwareHash": "6d7e81f6b6fb544929a7f5fbc9123b6a5ad49687dbd4528d2c5b91d0706ded2f", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap index 9b6bc31221..12fbe3d503 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_no_typenames_rust_qp.snap @@ -33,7 +33,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "set_context_no_typenames_rust_qp__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "30b465d83f1e94c76213a9de0297054a1966908533975406dd18d8db38130b21", + "schemaAwareHash": "025987a7a8c866dd913dc56c4dc6f3285bcd34035857ef0224ef6bebdc6b944b", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -79,7 +79,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "bcfcf2e249fac70efac867eff64799fd5eda2e87c4b426494880acb31cd006e7", + "schemaAwareHash": "ec32c05f19b6267dc408ac378410f75ad80e8dd4c62cacadea309aed04375958", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap index 217cee17b2..9154fbf1b6 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_rust_qp.snap @@ -35,7 +35,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "set_context_rust_qp__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "ae1c14ec3647fd1aafb1cf9940a17e60d5d52518e537ad31091ca5c0eca8c0ba", + "schemaAwareHash": "7b4176cae048d89760954a60ec441f2ee2508a5ac1eb4a6c123fc5cf8a930061", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -81,7 +81,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "6ab83f2051abc6b641bed7e54b923b7e0947a8ce837c2999d1db8a383084eebd", + "schemaAwareHash": "8fe3ef0b5c98418fd5201a62a97275c32e7177bb2e6a62dcc876d65043cbc647", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap index a2914a5cc2..c985004f1b 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch.snap @@ -33,7 +33,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query_type_mismatch__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "9ad83b20b30f763098f5273d5ad3cc9433743714de6ec2096bb03f47cbf99929", + "schemaAwareHash": "76744b6c5c054056f7aa9ebdd8ee4f64ee6534e49ededa336b7dae377d1224bc", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -79,7 +79,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "d28145b3f482f858ffe3ca1e23c381863e696e164b673041d8cdb145b0c55d40", + "schemaAwareHash": "d420e2fba88b355380ea18a55bc27b3aff8d776bd03d04d5f44e19402a4eff10", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap index 3e1fb23b4c..c27db78ff9 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_type_mismatch_rust_qp.snap @@ -33,7 +33,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query_type_mismatch__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "6ced4663657e945d34ad6a19a38998af7c347843b163a0982cfff305eba08854", + "schemaAwareHash": "bc701fd1cb3c50c87798d10c72214eee3997b27ad8bd4d3c0c3a6dd4941c354d", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -79,7 +79,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "0adeed095919e474cd2aa64764493eef3aea515cf3b2096c0648fc7828e20c9a", + "schemaAwareHash": "e23a1e560864aa0265191937008bdeaa05806cd33f10f63f4ee2f58457103c24", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_union.snap b/apollo-router/tests/snapshots/set_context__set_context_union.snap index 2cbce9e2eb..ce3c434108 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_union.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_union.snap @@ -32,7 +32,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "QueryUnion__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "28832c37359f453e10eba582489c8804e37259da3360561e6001a90794c76e09", + "schemaAwareHash": "5ca91ce52f6337db88ab61d494f5b3b52b37a4a37bf9efb386cec134e86d4660", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -81,7 +81,7 @@ snapshot_kind: text "typeCondition": "V" } ], - "schemaAwareHash": "30ac2f41c830481c78ded59222c0660a17cf960aba864a972ffe6075797c291d", + "schemaAwareHash": "bd757755f6a3cb0116e3a27612807f80a9ea376e3a8fe7bb2bff9c94290953dd", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" @@ -135,7 +135,7 @@ snapshot_kind: text "typeCondition": "V" } ], - "schemaAwareHash": "382811377545b242e2c43d61501a2de89f72f3ffa878fb5dc5692649917d0829", + "schemaAwareHash": "f4c7f9d3ce28970fcb8676c9808fa1609e2d88643bf9c43804311ecb4a4001e1", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" diff --git a/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap index 1a07a4019d..96098ca158 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_union_rust_qp.snap @@ -32,7 +32,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "QueryUnion__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "1befcaab6495299098243c1a7fba52f25acefab0bb32fdccc99d4a14c0aa329d", + "schemaAwareHash": "9ac5ac3e8e654a2bdcc70f655e4909b9cba143d055865f75da27f51f5d4fdea4", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -81,7 +81,7 @@ snapshot_kind: text "typeCondition": "V" } ], - "schemaAwareHash": "ead65648c76aeea3b7ebe38aa2a5d9c22c1290f6d16ee358d88b9e10b6b0bfde", + "schemaAwareHash": "79ecb3f9d1c195dceba17f3bf0198fad3c25a6a05e7181e07e7b9565a40d4127", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" @@ -134,7 +134,7 @@ snapshot_kind: text "typeCondition": "V" } ], - "schemaAwareHash": "dd845aa825a1f11609380aede33dde33277439e6f961d1d290f8759872c2657b", + "schemaAwareHash": "7418a461d65b6d0663c8cb55a22d2f84f8abcb5dd55cee5384323bf85e700ac9", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_1" diff --git a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap index 92b9baa5d1..868b7de485 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure.snap @@ -38,7 +38,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query_fetch_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "21c1fd295b8f17f7c410715dfdb15e0ed866da5a62d7902e0f21b7e95ff0297f", + "schemaAwareHash": "d6133b40599aaa7350d8c321d5313a7823d3430caab4c250754d24bb88ad0bce", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -77,7 +77,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "6721561884babef3ac12e05eb2038d2e810bff3c310a23b1b2d956652ac13b89", + "schemaAwareHash": "690a46547feb85f93bad65bf9c7015add2403adb114442971001b437549e45db", "serviceName": "Subgraph2", "variableUsages": [] }, @@ -129,7 +129,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "68db542f979e4f469a4286fade8e69d933ec57b71e8d5bcfcbe503d4c86c5add", + "schemaAwareHash": "5281c0f7b42b131f5e9a629d3340eac6026e5042580283b0f3d1b5892b351a22", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" diff --git a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap index 3b2838a0cb..a03ce09f0b 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_unrelated_fetch_failure_rust_qp.snap @@ -38,7 +38,7 @@ snapshot_kind: text "operationKind": "query", "operationName": "Query_fetch_failure__Subgraph1__0", "outputRewrites": null, - "schemaAwareHash": "9305e1c92eb20ac4467958e1003356b22f2f3537a50cc7745c3c9958add885d9", + "schemaAwareHash": "69aefb1c00e6c759f7238b7f4388bf0b5b8351cecf236e59a385165ccd4de986", "serviceName": "Subgraph1", "variableUsages": [] }, @@ -87,7 +87,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "8d4ddefb8baec1535ec6d10d4ec1db38bd0cb05933efab7d7097f069867e7e30", + "schemaAwareHash": "a2d9d5ae511effd9280bdf0cde021c36206e6e578e1d6722a74584cdec287f8b", "serviceName": "Subgraph1", "variableUsages": [ "contextualArgument_1_0" @@ -130,7 +130,7 @@ snapshot_kind: text "typeCondition": "U" } ], - "schemaAwareHash": "9bf77af5fd96f9da379241494705d6d5a1c41929975f4dffd83596c5351141c9", + "schemaAwareHash": "eda16e56540e88943000a1936786574f5da632ea4d4ab73b49cea306db8f9b25", "serviceName": "Subgraph2", "variableUsages": [] }, diff --git a/apollo-router/tests/snapshots/set_context__set_context_with_null.snap b/apollo-router/tests/snapshots/set_context__set_context_with_null.snap index 3ee08bb57c..6c03832503 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_with_null.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_with_null.snap @@ -30,7 +30,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "e6208acfdfd0841365a3b63a8fcff118daf4ebdffce940c1e951abe6f0e551c4", + "schemaAwareHash": "72f6c5c3c41936eba859c4327265e74c9421e41d684ce560f3cc5c0a1bef201f", "authorization": { "is_authenticated": false, "scopes": [], @@ -83,7 +83,7 @@ snapshot_kind: text "renameKeyTo": "contextualArgument_1_0" } ], - "schemaAwareHash": "42e5f12379b7136efe99706e8569cf56618742fbf4cef43fa44347e441b6a04d", + "schemaAwareHash": "2d6f86d4ed32670400197090358c53094c0f83892f3016ac1d067663d215b83a", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap b/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap index 3c2696a780..0527808fc7 100644 --- a/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap +++ b/apollo-router/tests/snapshots/set_context__set_context_with_null_rust_qp.snap @@ -30,7 +30,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "18757152409a0e2ea274a9cffe092fcb8c85a1e85d030d1d3528ceecbb9e1c5d", + "schemaAwareHash": "3a42fbf2a9a7f48e3ed94f72391fef2af7a06310b2ac92e4ee76c2ceb24507fb", "authorization": { "is_authenticated": false, "scopes": [], @@ -82,7 +82,7 @@ snapshot_kind: text "renameKeyTo": "contextualArgument_1_0" } ], - "schemaAwareHash": "913186d70ede74717b3ceb17f38dda8a39e8a8c2eefb903b18ecce8c0c6e98ce", + "schemaAwareHash": "72ee0ea9ed33e8ce0736bb392a654d4cf6f9316809be1e9b0aed00842b6e37a9", "authorization": { "is_authenticated": false, "scopes": [], 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 32e8231395..a0994540d9 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 @@ -80,7 +80,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5e7085d44036286e5fca029a1f3fd6be1791fa1665597bff009141ee370ee279", + "schemaAwareHash": "d406d6b0a5762bf096ec0e86318ae6485042b9bc7190417330783148728e9ed3", "authorization": { "is_authenticated": false, "scopes": [], @@ -138,7 +138,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "e386fd2fcbd895c94bae09682c354184e8081225d524060f54ab69d3bca8cf02", + "schemaAwareHash": "6ec77a0c610f95d5709448368fcaeaf82cff4d5264213c90a9bea6648aa4fb91", "authorization": { "is_authenticated": false, "scopes": [], 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 dcb16c501e..459fb3dd51 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 @@ -80,7 +80,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "ad3dd3ed27be8f5048e968c8295aafc42587e6dafc501a690c4ce0ee5d03e2d2", + "schemaAwareHash": "49f8587a3706924dd91c4ed142e4cb7341599769c6f2e7e974b683390c378771", "authorization": { "is_authenticated": false, "scopes": [], @@ -138,7 +138,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", + "schemaAwareHash": "2eb874d1637f6040c73f22dc50551f321610897debe931d1a3cb448227cfb679", "authorization": { "is_authenticated": false, "scopes": [], 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 62938baac1..31d8866704 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 @@ -80,7 +80,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5e7085d44036286e5fca029a1f3fd6be1791fa1665597bff009141ee370ee279", + "schemaAwareHash": "d406d6b0a5762bf096ec0e86318ae6485042b9bc7190417330783148728e9ed3", "authorization": { "is_authenticated": false, "scopes": [], @@ -141,7 +141,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", + "schemaAwareHash": "ca74ee896977e09e7467fdc5a03698e748c88209df8c84f85293bd63cb4afa8b", "authorization": { "is_authenticated": false, "scopes": [], @@ -200,7 +200,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", + "schemaAwareHash": "692bb14128b6c838ddc7223c195fd6c47ef867685f195e88002b918d11be065e", "authorization": { "is_authenticated": false, "scopes": [], 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 0f96dd030c..c7e3f4a1ed 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 @@ -80,7 +80,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "ad3dd3ed27be8f5048e968c8295aafc42587e6dafc501a690c4ce0ee5d03e2d2", + "schemaAwareHash": "49f8587a3706924dd91c4ed142e4cb7341599769c6f2e7e974b683390c378771", "authorization": { "is_authenticated": false, "scopes": [], @@ -142,7 +142,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", + "schemaAwareHash": "2eb874d1637f6040c73f22dc50551f321610897debe931d1a3cb448227cfb679", "authorization": { "is_authenticated": false, "scopes": [], @@ -202,7 +202,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", + "schemaAwareHash": "ce53c44a5993b8f0d085dddde949dfadc615d385821c70fe6b43338b2abf732a", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap index 62938baac1..31d8866704 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments-2.snap @@ -80,7 +80,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5e7085d44036286e5fca029a1f3fd6be1791fa1665597bff009141ee370ee279", + "schemaAwareHash": "d406d6b0a5762bf096ec0e86318ae6485042b9bc7190417330783148728e9ed3", "authorization": { "is_authenticated": false, "scopes": [], @@ -141,7 +141,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", + "schemaAwareHash": "ca74ee896977e09e7467fdc5a03698e748c88209df8c84f85293bd63cb4afa8b", "authorization": { "is_authenticated": false, "scopes": [], @@ -200,7 +200,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", + "schemaAwareHash": "692bb14128b6c838ddc7223c195fd6c47ef867685f195e88002b918d11be065e", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap index 0f96dd030c..c7e3f4a1ed 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_generate_query_fragments.snap @@ -80,7 +80,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "ad3dd3ed27be8f5048e968c8295aafc42587e6dafc501a690c4ce0ee5d03e2d2", + "schemaAwareHash": "49f8587a3706924dd91c4ed142e4cb7341599769c6f2e7e974b683390c378771", "authorization": { "is_authenticated": false, "scopes": [], @@ -142,7 +142,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", + "schemaAwareHash": "2eb874d1637f6040c73f22dc50551f321610897debe931d1a3cb448227cfb679", "authorization": { "is_authenticated": false, "scopes": [], @@ -202,7 +202,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", + "schemaAwareHash": "ce53c44a5993b8f0d085dddde949dfadc615d385821c70fe6b43338b2abf732a", "authorization": { "is_authenticated": false, "scopes": [], 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 757fdd9556..2258fe8e2d 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 @@ -142,7 +142,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "9191ecc2fda635c0dde0e40b3656760f28a5da08198b3512764c3172d5783856", + "schemaAwareHash": "1632c390b36440b872e929531433045c45d543b28ee5452c8e2ed29e989216a5", "authorization": { "is_authenticated": false, "scopes": [], @@ -204,7 +204,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", + "schemaAwareHash": "ca74ee896977e09e7467fdc5a03698e748c88209df8c84f85293bd63cb4afa8b", "authorization": { "is_authenticated": false, "scopes": [], @@ -264,7 +264,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", + "schemaAwareHash": "692bb14128b6c838ddc7223c195fd6c47ef867685f195e88002b918d11be065e", "authorization": { "is_authenticated": false, "scopes": [], 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 3d5668e6c6..e09ccb07fe 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 @@ -142,7 +142,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "ae9c32852d8a2f9e0fec54ade465709b59218cd64b7e7c551d0df3e1c1be43e0", + "schemaAwareHash": "5b69082c3a9883827a3d6a870dfe6f9aeb191372d2ebc2766075a31e207487d4", "authorization": { "is_authenticated": false, "scopes": [], @@ -205,7 +205,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", + "schemaAwareHash": "2eb874d1637f6040c73f22dc50551f321610897debe931d1a3cb448227cfb679", "authorization": { "is_authenticated": false, "scopes": [], @@ -266,7 +266,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", + "schemaAwareHash": "ce53c44a5993b8f0d085dddde949dfadc615d385821c70fe6b43338b2abf732a", "authorization": { "is_authenticated": false, "scopes": [], 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 2f8650485e..b8561c29af 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 @@ -146,7 +146,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3db19df4fd1b36e4ed279e01e3a31cb0843e8f9dfdb9876bfcd09cf223f27aa3", + "schemaAwareHash": "a6412469787fe50d6d640f808950d84a1fbd4f4599d8ad2d2b50bee125f032cf", "authorization": { "is_authenticated": false, "scopes": [], @@ -209,7 +209,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "3dcb6331dc1a5bb5facf37e13d119d58797bdcce300c9b6c97ec2da69cc84159", + "schemaAwareHash": "ca74ee896977e09e7467fdc5a03698e748c88209df8c84f85293bd63cb4afa8b", "authorization": { "is_authenticated": false, "scopes": [], @@ -270,7 +270,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "cac91803ad01fddb5799627a3eaa27f37f8a7583a991353979248f1486a699c7", + "schemaAwareHash": "692bb14128b6c838ddc7223c195fd6c47ef867685f195e88002b918d11be065e", "authorization": { "is_authenticated": false, "scopes": [], 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 b8363c3f85..72bc30f09f 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 @@ -146,7 +146,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "76dee51cf4c0515d390c58da3fd7a084589834f8cbe9f96dc725f0b344fb4f98", + "schemaAwareHash": "4e47b6cd403425cc9181e698a31bd562e5b54d24f31533ceb2d24ac0011d185a", "authorization": { "is_authenticated": false, "scopes": [], @@ -210,7 +210,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "6a7d111062f9d804f15c1e4da59dc0f2d0ce88342527b3b172ce973540223ce1", + "schemaAwareHash": "2eb874d1637f6040c73f22dc50551f321610897debe931d1a3cb448227cfb679", "authorization": { "is_authenticated": false, "scopes": [], @@ -272,7 +272,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "eccbbe92d496c0b13c396fba7d0cc5e1de878e18c861afd30acf1f4cfa67f961", + "schemaAwareHash": "ce53c44a5993b8f0d085dddde949dfadc615d385821c70fe6b43338b2abf732a", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap index 86303e3a96..f89cde6b32 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch-2.snap @@ -55,7 +55,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "434b300a2320dc017f003077aa17171613350baaa806426e88d724d1a5c01600", + "schemaAwareHash": "3f0b3f09181fe1a524e02ea7ae290aac97f6c5583cbde41c7073dab6af79690a", "authorization": { "is_authenticated": false, "scopes": [], @@ -116,7 +116,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "5fc15a41a51385410e8fc992c29f3dfb9db55c82c9cb6f63519d2954a119355a", + "schemaAwareHash": "5b3ed44a13782c7a73009a76a6906a407c57538d4c26a6251b4d4b1253730923", "authorization": { "is_authenticated": false, "scopes": [], @@ -175,7 +175,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "f571d05338d7b212a3a98e5e685ae3f69cad5a512af1004ebcc3cef772ba6dd2", + "schemaAwareHash": "0cb0308f000c80067924c40cb212dd2323fd2081621bf557bf87354c2a9b6a06", "authorization": { "is_authenticated": false, "scopes": [], diff --git a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap index 30a3af074e..6c85615f91 100644 --- a/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap +++ b/apollo-router/tests/snapshots/type_conditions___test_type_conditions_enabled_shouldnt_make_article_fetch.snap @@ -55,7 +55,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "c9b833d9f2b0b0c67a58c9c69893584f46f8c9e8185b745aa69edf1b48698489", + "schemaAwareHash": "61cb2471139d116a5166d71dd819be25f5ec3b3dfec204cd07222a03d3b31628", "authorization": { "is_authenticated": false, "scopes": [], @@ -117,7 +117,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "ba9e1b441ac7bc2cfbc633e58ef2302635a247dd9e97cc24f027c5334d22966d", + "schemaAwareHash": "8435549983472ccaa79626c0dc47ca4cabbf37305345a65d1a40c7157888c18a", "authorization": { "is_authenticated": false, "scopes": [], @@ -177,7 +177,7 @@ snapshot_kind: text "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "c66770a56203e72289af611bc6bde0ffe0248d8b63db2a63d94e4e889e888116", + "schemaAwareHash": "0dc7538d481aac9723a7ae86dfa1499f1595b90c86d7b2fe500be89511436746", "authorization": { "is_authenticated": false, "scopes": [], From 73fdc2043c3d83dda0d28759de2d2cd295e59a4c Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Wed, 22 Jan 2025 15:00:22 +0200 Subject: [PATCH 32/38] SchemaId => SchemaHash --- .../query_planner/caching_query_planner.rs | 4 ++-- apollo-router/src/query_planner/fetch.rs | 6 ++--- apollo-router/src/router_factory.rs | 2 +- apollo-router/src/spec/mod.rs | 2 +- apollo-router/src/spec/schema.rs | 22 +++++++++---------- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/apollo-router/src/query_planner/caching_query_planner.rs b/apollo-router/src/query_planner/caching_query_planner.rs index 0c1ec598b1..3d8137a709 100644 --- a/apollo-router/src/query_planner/caching_query_planner.rs +++ b/apollo-router/src/query_planner/caching_query_planner.rs @@ -43,7 +43,7 @@ use crate::services::QueryPlannerRequest; use crate::services::QueryPlannerResponse; use crate::spec::QueryHash; use crate::spec::Schema; -use crate::spec::SchemaId; +use crate::spec::SchemaHash; use crate::spec::SpecError; use crate::Configuration; @@ -652,7 +652,7 @@ pub(crate) struct CachingQueryKey { // XXX(@goto-bus-stop): It's probably correct to remove this, since having it here is // misleading. The schema ID is *not* used in the Redis cache, but it's okay because the QueryHash // is schema-aware. - pub(crate) schema_id: SchemaId, + pub(crate) schema_id: SchemaHash, pub(crate) metadata: CacheKeyMetadata, pub(crate) plan_options: PlanOptions, pub(crate) config_mode_hash: Arc, diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index 495132220a..cfca530f3d 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -35,7 +35,7 @@ use crate::plugins::authorization::CacheKeyMetadata; use crate::services::SubgraphRequest; use crate::spec::QueryHash; use crate::spec::Schema; -use crate::spec::SchemaId; +use crate::spec::SchemaHash; /// GraphQL operation type. #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash, Deserialize, Serialize)] @@ -99,7 +99,7 @@ pub(crate) type SubgraphSchemas = HashMap; pub(crate) struct SubgraphSchema { pub(crate) schema: Arc>, // TODO: Ideally should have separate nominal type for subgraph's schema hash - pub(crate) hash: Arc, + pub(crate) hash: Arc, } impl SubgraphSchema { @@ -107,7 +107,7 @@ impl SubgraphSchema { let sdl = schema.serialize().no_indent().to_string(); Self { schema: Arc::new(schema), - hash: Arc::new(SchemaId::new(&sdl)), + hash: Arc::new(SchemaHash::new(&sdl)), } } } diff --git a/apollo-router/src/router_factory.rs b/apollo-router/src/router_factory.rs index 843f70e284..e2e6d7ffac 100644 --- a/apollo-router/src/router_factory.rs +++ b/apollo-router/src/router_factory.rs @@ -741,7 +741,7 @@ pub(crate) async fn create_plugins( } fn inject_schema_id( - // Ideally we'd use &SchemaId, but we'll need to update a bunch of tests to do so + // Ideally we'd use &SchemaHash, but we'll need to update a bunch of tests to do so schema_id: &str, configuration: &mut Value, ) { diff --git a/apollo-router/src/spec/mod.rs b/apollo-router/src/spec/mod.rs index ae682a9b42..948751b8a8 100644 --- a/apollo-router/src/spec/mod.rs +++ b/apollo-router/src/spec/mod.rs @@ -16,7 +16,7 @@ pub(crate) use query::Query; pub(crate) use query::TYPENAME; pub(crate) use schema::QueryHash; pub(crate) use schema::Schema; -pub(crate) use schema::SchemaId; +pub(crate) use schema::SchemaHash; pub(crate) use selection::*; use serde::Deserialize; use serde::Serialize; diff --git a/apollo-router/src/spec/schema.rs b/apollo-router/src/spec/schema.rs index 6bbcb00bb6..42a3f63b5e 100644 --- a/apollo-router/src/spec/schema.rs +++ b/apollo-router/src/spec/schema.rs @@ -33,7 +33,7 @@ pub(crate) struct Schema { subgraphs: HashMap, pub(crate) implementers_map: apollo_compiler::collections::HashMap, api_schema: ApiSchema, - pub(crate) schema_id: SchemaId, + pub(crate) schema_id: SchemaHash, pub(crate) launch_id: Option>, } @@ -152,8 +152,8 @@ impl Schema { } /// Compute the Schema ID for an SDL string. - pub(crate) fn schema_id(sdl: &str) -> SchemaId { - SchemaId::new(sdl) + pub(crate) fn schema_id(sdl: &str) -> SchemaHash { + SchemaHash::new(sdl) } /// Extracts a string containing the entire [`Schema`]. @@ -369,7 +369,7 @@ impl std::ops::Deref for ApiSchema { /// That means that differences in whitespace and comments affect the hash, not only semantic /// differences in the schema. #[derive(Debug, Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] -pub(crate) struct SchemaId( +pub(crate) struct SchemaHash( /// The internal representation is a pointer to a string. /// This is not ideal, it might be better eg. to just have a fixed-size byte array that can be /// turned into a string as needed. @@ -377,7 +377,7 @@ pub(crate) struct SchemaId( /// essentially a backwards compatibility decision. Arc, ); -impl SchemaId { +impl SchemaHash { pub(crate) fn new(sdl: &str) -> Self { let mut hasher = Sha256::new(); hasher.update(sdl); @@ -407,7 +407,7 @@ impl SchemaId { } } -impl Display for SchemaId { +impl Display for SchemaHash { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0.as_str()) } @@ -419,13 +419,13 @@ impl Display for SchemaId { /// For a document with two queries A and B, queries A and B will result in a different hash even /// if the document text is identical. /// If query A is then executed against two different versions of the schema, the hash will be -/// different again, depending on the [SchemaId]. +/// different again, depending on the [SchemaHash]. /// -/// A query hash can be obtained from a schema ID using [SchemaId::operation_hash]. +/// A query hash can be obtained from a schema ID using [SchemaHash::operation_hash]. // FIXME: rename to OperationHash since it include operation name? #[derive(Clone, Hash, PartialEq, Eq, Deserialize, Serialize)] pub(crate) struct QueryHash( - /// Unlike SchemaId, the query hash has no backwards compatibility motivations for the internal + /// Unlike SchemaHash, the query hash has no backwards compatibility motivations for the internal /// type, as it's fully private. We could consider making this a fixed-size byte array rather /// than a Vec, but it shouldn't make a huge difference. #[serde(with = "hex")] @@ -433,8 +433,8 @@ pub(crate) struct QueryHash( ); impl QueryHash { - /// This constructor is not public, see [SchemaId::operation_hash] instead. - fn new(schema_id: &SchemaId, query_text: &str, operation_name: Option<&str>) -> Self { + /// This constructor is not public, see [SchemaHash::operation_hash] instead. + fn new(schema_id: &SchemaHash, query_text: &str, operation_name: Option<&str>) -> Self { let mut hasher = Sha256::new(); hasher.update(schema_id.as_str()); // byte separator between each part that is hashed From cc4e27ab945b683241694e78ad540305dc9679de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Wed, 22 Jan 2025 16:40:11 +0100 Subject: [PATCH 33/38] Formatting fix --- apollo-router/src/query_planner/query_planner_service.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apollo-router/src/query_planner/query_planner_service.rs b/apollo-router/src/query_planner/query_planner_service.rs index edd256cd4f..68e57c62f6 100644 --- a/apollo-router/src/query_planner/query_planner_service.rs +++ b/apollo-router/src/query_planner/query_planner_service.rs @@ -192,7 +192,7 @@ impl QueryPlannerService { .map(|(name, schema)| { ( name.to_string(), - SubgraphSchema::new(schema.schema().clone()) + SubgraphSchema::new(schema.schema().clone()), ) }) .collect(), From ab9c21d42b2f90cfead15bb46374738ca22117bd Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Thu, 23 Jan 2025 02:20:23 +0200 Subject: [PATCH 34/38] update keys in Redis tests --- apollo-router/tests/integration/redis.rs | 22 +++++++++---------- ...tegration__redis__query_planner_cache.snap | 3 ++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apollo-router/tests/integration/redis.rs b/apollo-router/tests/integration/redis.rs index 07d16d7b92..82c8de8abd 100644 --- a/apollo-router/tests/integration/redis.rs +++ b/apollo-router/tests/integration/redis.rs @@ -52,7 +52,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 = &format!( - "plan:router:{}:8c0b4bfb4630635c2b5748c260d686ddb301d164e5818c63d6d9d77e13631676:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:d9f7a00bc249cb51cfc8599f86b6dc5272967b37b1409dc4717f105b6939fe43", + "plan:router:{}:47939f0e964372951934fc662c9c2be675bc7116ec3e57029abe555284eb10a4:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:d9f7a00bc249cb51cfc8599f86b6dc5272967b37b1409dc4717f105b6939fe43", env!("CARGO_PKG_VERSION") ); @@ -453,13 +453,13 @@ async fn entity_cache_basic() -> Result<(), BoxError> { // if this is failing due to a cache key change, hook up redis-cli with the MONITOR command to see the keys being set let s:String = client - .get("version:1.0:subgraph:products:type:Query:hash:5e8ac155fe1fb5b3b69292f89b7df818a39d88a3bf77031a6bd60c22eeb4b242:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") + .get("version:1.0:subgraph:products:type:Query:hash:30cf92cd31bc204de344385c8f6d90a53da6c9180d80e8f7979a5bc19cd96055:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") .await .unwrap(); let v: Value = serde_json::from_str(&s).unwrap(); insta::assert_json_snapshot!(v.as_object().unwrap().get("data").unwrap()); - let s: String = client.get("version:1.0:subgraph:reviews:type:Product:entity:4911f7a9dbad8a47b8900d65547503a2f3c0359f65c0bc5652ad9b9843281f66:hash:50354623eb0a347d47a62f002fae74c0f579ee693af1fdb9a1e4744b4723dd2c:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c").await.unwrap(); + let s: String = client.get("version:1.0:subgraph:reviews:type:Product:entity:4911f7a9dbad8a47b8900d65547503a2f3c0359f65c0bc5652ad9b9843281f66:hash:b9b8a9c94830cf56329ec2db7d7728881a6ba19cc1587710473e732e775a5870:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c").await.unwrap(); let v: Value = serde_json::from_str(&s).unwrap(); insta::assert_json_snapshot!(v.as_object().unwrap().get("data").unwrap()); @@ -571,7 +571,7 @@ async fn entity_cache_basic() -> Result<(), BoxError> { insta::assert_json_snapshot!(response); let s:String = client - .get("version:1.0:subgraph:reviews:type:Product:entity:d9a4cd73308dd13ca136390c10340823f94c335b9da198d2339c886c738abf0d:hash:50354623eb0a347d47a62f002fae74c0f579ee693af1fdb9a1e4744b4723dd2c:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") + .get("version:1.0:subgraph:reviews:type:Product:entity:d9a4cd73308dd13ca136390c10340823f94c335b9da198d2339c886c738abf0d:hash:b9b8a9c94830cf56329ec2db7d7728881a6ba19cc1587710473e732e775a5870:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") .await .unwrap(); let v: Value = serde_json::from_str(&s).unwrap(); @@ -800,7 +800,7 @@ async fn entity_cache_authorization() -> Result<(), BoxError> { insta::assert_json_snapshot!(response); let s:String = client - .get("version:1.0:subgraph:products:type:Query:hash:5e8ac155fe1fb5b3b69292f89b7df818a39d88a3bf77031a6bd60c22eeb4b242:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") + .get("version:1.0:subgraph:products:type:Query:hash:30cf92cd31bc204de344385c8f6d90a53da6c9180d80e8f7979a5bc19cd96055:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") .await .unwrap(); let v: Value = serde_json::from_str(&s).unwrap(); @@ -821,7 +821,7 @@ async fn entity_cache_authorization() -> Result<(), BoxError> { ); let s: String = client - .get("version:1.0:subgraph:reviews:type:Product:entity:4911f7a9dbad8a47b8900d65547503a2f3c0359f65c0bc5652ad9b9843281f66:hash:50354623eb0a347d47a62f002fae74c0f579ee693af1fdb9a1e4744b4723dd2c:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") + .get("version:1.0:subgraph:reviews:type:Product:entity:4911f7a9dbad8a47b8900d65547503a2f3c0359f65c0bc5652ad9b9843281f66:hash:b9b8a9c94830cf56329ec2db7d7728881a6ba19cc1587710473e732e775a5870:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") .await .unwrap(); let v: Value = serde_json::from_str(&s).unwrap(); @@ -865,7 +865,7 @@ async fn entity_cache_authorization() -> Result<(), BoxError> { insta::assert_json_snapshot!(response); let s:String = client - .get("version:1.0:subgraph:reviews:type:Product:entity:4911f7a9dbad8a47b8900d65547503a2f3c0359f65c0bc5652ad9b9843281f66:hash:2253830e3b366dcfdfa4e1acf6afa9e05d3c80ff50171243768a3e416536c89b:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") + .get("version:1.0:subgraph:reviews:type:Product:entity:4911f7a9dbad8a47b8900d65547503a2f3c0359f65c0bc5652ad9b9843281f66:hash:572a2cdde770584306cd0def24555773323b1738e9a303c7abc1721b6f9f2ec4:data:d9d84a3c7ffc27b0190a671212f3740e5b8478e84e23825830e97822e25cf05c") .await .unwrap(); let v: Value = serde_json::from_str(&s).unwrap(); @@ -992,7 +992,7 @@ async fn query_planner_redis_update_query_fragments() { // This configuration turns the fragment generation option *off*. include_str!("fixtures/query_planner_redis_config_update_query_fragments.router.yaml"), &format!( - "plan:router:{}:5938623f2155169070684a48be1e0b8468d0f2c662b5527a2247f683173f7d05:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:fb1a8e6e454ad6a1d0d48b24dc9c7c4dd6d9bf58b6fdaf43cd24eb77fbbb3a17", + "plan:router:{}:14ece7260081620bb49f1f4934cf48510e5f16c3171181768bb46a5609d7dfb7:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:fb1a8e6e454ad6a1d0d48b24dc9c7c4dd6d9bf58b6fdaf43cd24eb77fbbb3a17", env!("CARGO_PKG_VERSION") ), ) @@ -1015,7 +1015,7 @@ async fn query_planner_redis_update_defer() { test_redis_query_plan_config_update( include_str!("fixtures/query_planner_redis_config_update_defer.router.yaml"), &format!( - "plan:router:{}:5938623f2155169070684a48be1e0b8468d0f2c662b5527a2247f683173f7d05:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:dc062fcc9cfd9582402d1e8b1fa3ee336ea1804d833443869e0b3744996716a2", + "plan:router:{}:14ece7260081620bb49f1f4934cf48510e5f16c3171181768bb46a5609d7dfb7:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:dc062fcc9cfd9582402d1e8b1fa3ee336ea1804d833443869e0b3744996716a2", env!("CARGO_PKG_VERSION") ), ) @@ -1040,7 +1040,7 @@ async fn query_planner_redis_update_type_conditional_fetching() { "fixtures/query_planner_redis_config_update_type_conditional_fetching.router.yaml" ), &format!( - "plan:router:{}:5938623f2155169070684a48be1e0b8468d0f2c662b5527a2247f683173f7d05:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:bdc09980aa6ef28a67f5aeb8759763d8ac5a4fc43afa8c5a89f58cc998c48db3", + "plan:router:{}:14ece7260081620bb49f1f4934cf48510e5f16c3171181768bb46a5609d7dfb7:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:bdc09980aa6ef28a67f5aeb8759763d8ac5a4fc43afa8c5a89f58cc998c48db3", env!("CARGO_PKG_VERSION") ), ) @@ -1068,7 +1068,7 @@ async fn test_redis_query_plan_config_update(updated_config: &str, new_cache_key // If the tests above are failing, this is the key that needs to be changed first. let starting_key = &format!( - "plan:router:{}:5938623f2155169070684a48be1e0b8468d0f2c662b5527a2247f683173f7d05:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:d9f7a00bc249cb51cfc8599f86b6dc5272967b37b1409dc4717f105b6939fe43", + "plan:router:{}:14ece7260081620bb49f1f4934cf48510e5f16c3171181768bb46a5609d7dfb7:opname:3973e022e93220f9212c18d0d0c543ae7c309e46640da93a4a0314de999f5112:metadata:d9f7a00bc249cb51cfc8599f86b6dc5272967b37b1409dc4717f105b6939fe43", env!("CARGO_PKG_VERSION") ); 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."); diff --git a/apollo-router/tests/integration/snapshots/integration_tests__integration__redis__query_planner_cache.snap b/apollo-router/tests/integration/snapshots/integration_tests__integration__redis__query_planner_cache.snap index 7f7fd862db..31853fcf98 100644 --- a/apollo-router/tests/integration/snapshots/integration_tests__integration__redis__query_planner_cache.snap +++ b/apollo-router/tests/integration/snapshots/integration_tests__integration__redis__query_planner_cache.snap @@ -1,6 +1,7 @@ --- source: apollo-router/tests/integration/redis.rs expression: query_plan +snapshot_kind: text --- { "kind": "Fetch", @@ -13,7 +14,7 @@ expression: query_plan "inputRewrites": null, "outputRewrites": null, "contextRewrites": null, - "schemaAwareHash": "b86f4d9d705538498ec90551f9d90f9eee4386be36ad087638932dad3f44bf66", + "schemaAwareHash": "4f17a8ba2e5371d2d476e8824ffa2ecb3fc18440ad04cff216d65e33287a7cd3", "authorization": { "is_authenticated": false, "scopes": [], From a4404f3d8b90a85f038058146b25d362e7faed33 Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Thu, 23 Jan 2025 02:42:09 +0200 Subject: [PATCH 35/38] add changelog --- .changesets/fix_query_hash_speedup.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changesets/fix_query_hash_speedup.md diff --git a/.changesets/fix_query_hash_speedup.md b/.changesets/fix_query_hash_speedup.md new file mode 100644 index 0000000000..fe66cf05a3 --- /dev/null +++ b/.changesets/fix_query_hash_speedup.md @@ -0,0 +1,7 @@ +### Improve performance of query hashing by using a precomputed schema hash ([PR #6622](https://github.com/apollographql/router/pull/6622)) + +The router now uses a simpler and faster query hashing algorithm with more predictable CPU and memory usage. This improvement is enabled by using a precomputed hash of the entire schema, rather than computing and hashing the subset of types and fields used by each query. + +For more details on why these design decisions were made, please see the [PR description](https://github.com/apollographql/router/pull/6622) + +By [@IvanGoncharov](https://github.com/IvanGoncharov) in https://github.com/apollographql/router/pull/6622 \ No newline at end of file From 23dedd1a7f653371d50b05148ece43afe6921b5e Mon Sep 17 00:00:00 2001 From: Ivan Goncharov Date: Thu, 23 Jan 2025 02:47:18 +0200 Subject: [PATCH 36/38] Update apollo-router/src/router_factory.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Renée --- apollo-router/src/router_factory.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apollo-router/src/router_factory.rs b/apollo-router/src/router_factory.rs index dd57824d44..54c2c85922 100644 --- a/apollo-router/src/router_factory.rs +++ b/apollo-router/src/router_factory.rs @@ -166,9 +166,7 @@ impl RouterSuperServiceFactory for YamlRouterFactory { PluginInit::builder() .config(plugin_config.clone()) .supergraph_sdl(schema.raw_sdl.clone()) - .supergraph_schema_id(Arc::new( - schema.schema_id.as_str().to_owned(), - )) + .supergraph_schema_id(schema.schema_id.clone().into_inner()) .supergraph_schema(Arc::new(schema.supergraph_schema().clone())) .notify(configuration.notify.clone()) .build(), From 67815a5b947255d07ec0eaaa1083fe2c38108433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Thu, 23 Jan 2025 14:47:52 +0100 Subject: [PATCH 37/38] Re-add test --- apollo-router/src/query_planner/tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apollo-router/src/query_planner/tests.rs b/apollo-router/src/query_planner/tests.rs index ab90ec2d0f..babf395514 100644 --- a/apollo-router/src/query_planner/tests.rs +++ b/apollo-router/src/query_planner/tests.rs @@ -1888,6 +1888,10 @@ fn broken_plan_does_not_panic() { query_planner::fetch::SubgraphSchema::new(subgraph_schema), ); // Run the plan initialization code to make sure it doesn't panic. - let _result = + let result = Arc::make_mut(&mut plan.root).init_parsed_operations_and_hash_subqueries(&subgraph_schemas); + assert_eq!( + result.unwrap_err().to_string(), + r#"[1:3] Cannot query field "invalid" on type "Query"."# + ); } From f4e8b7f1188c0ca018cd2a42fea940f4ad97cf88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9e=20Kooi?= Date: Thu, 23 Jan 2025 14:51:17 +0100 Subject: [PATCH 38/38] Un-double-Arc SchemaHash in fetch.rs --- apollo-router/src/query_planner/fetch.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apollo-router/src/query_planner/fetch.rs b/apollo-router/src/query_planner/fetch.rs index fc937d2695..80922805eb 100644 --- a/apollo-router/src/query_planner/fetch.rs +++ b/apollo-router/src/query_planner/fetch.rs @@ -101,7 +101,7 @@ pub(crate) type SubgraphSchemas = HashMap; pub(crate) struct SubgraphSchema { pub(crate) schema: Arc>, // TODO: Ideally should have separate nominal type for subgraph's schema hash - pub(crate) hash: Arc, + pub(crate) hash: SchemaHash, } impl SubgraphSchema { @@ -109,7 +109,7 @@ impl SubgraphSchema { let sdl = schema.serialize().no_indent().to_string(); Self { schema: Arc::new(schema), - hash: Arc::new(SchemaHash::new(&sdl)), + hash: SchemaHash::new(&sdl), } } }