From 1c5fd9b22a16a274be32aa42b6cee4247c03644c Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 00:38:01 +0200 Subject: [PATCH 01/17] Enhanced Fusion QueryPlan Information --- .../CacheControlConstraintsOptimizer.cs | 2 +- .../src/Core/Execution/ExecutionState.cs | 230 +++------------- .../src/Core/Execution/ExecutorUtils.cs | 30 +- .../Core/Execution/FederatedQueryContext.cs | 4 +- .../Core/Execution/FusionContextExtensions.cs | 4 +- .../Fusion/src/Core/Execution/RequestState.cs | 194 +++++++++++++ .../src/Core/Execution/SelectionSetState.cs | 55 ---- .../src/Core/HotChocolate.Fusion.csproj | 3 + .../ExecutionNodeBuilderMiddleware.cs | 35 ++- .../Core/Planning/ExportDefinitionRegistry.cs | 15 +- .../Fusion/src/Core/Planning/Nodes/Compose.cs | 21 +- .../Fusion/src/Core/Planning/Nodes/If.cs | 2 +- .../src/Core/Planning/Nodes/Introspect.cs | 2 +- .../src/Core/Planning/Nodes/Parallel.cs | 2 +- .../src/Core/Planning/Nodes/QueryPlanNode.cs | 4 +- .../Nodes/ReformatVariableRewriter.cs | 33 +++ .../Fusion/src/Core/Planning/Nodes/Resolve.cs | 156 +++++------ .../Core/Planning/Nodes/ResolveByKeyBatch.cs | 257 +++++++---------- .../src/Core/Planning/Nodes/ResolveNode.cs | 2 +- .../Planning/Nodes/ResolverNodeBase.Config.cs | 130 +++++++++ .../Core/Planning/Nodes/ResolverNodeBase.cs | 258 +++++++++--------- .../RequestDocumentFormatter.cs | 18 +- .../src/Core/Utilities/CollectionUtils.cs | 67 +++++ .../Utilities/Utf8QueryPlanPropertyNames.cs | 22 ++ 24 files changed, 873 insertions(+), 673 deletions(-) create mode 100644 src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs delete mode 100644 src/HotChocolate/Fusion/src/Core/Execution/SelectionSetState.cs create mode 100644 src/HotChocolate/Fusion/src/Core/Planning/Nodes/ReformatVariableRewriter.cs create mode 100644 src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs create mode 100644 src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs create mode 100644 src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs diff --git a/src/HotChocolate/Caching/src/Caching/CacheControlConstraintsOptimizer.cs b/src/HotChocolate/Caching/src/Caching/CacheControlConstraintsOptimizer.cs index 5dabdbda16c..e781c3b037f 100644 --- a/src/HotChocolate/Caching/src/Caching/CacheControlConstraintsOptimizer.cs +++ b/src/HotChocolate/Caching/src/Caching/CacheControlConstraintsOptimizer.cs @@ -100,7 +100,7 @@ private static void ProcessSelection( foreach (var type in possibleTypes) { - var selectionSet = (SelectionSet)operation.GetSelectionSet(selection, type); + var selectionSet = Unsafe.As(operation.GetSelectionSet(selection, type)); var length = selectionSet.Selections.Count; ref var start = ref selectionSet.GetSelectionsReference(); diff --git a/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs b/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs index d05b3043e06..46173b46c1e 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs @@ -1,197 +1,55 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Threading; using HotChocolate.Execution.Processing; -using static HotChocolate.Fusion.FusionResources; +using HotChocolate.Language; namespace HotChocolate.Fusion.Execution; +/// +/// Represents the query plan state for a single selection set. +/// This working state can be shared between nodes of a query plan. +/// internal sealed class ExecutionState { - private readonly Dictionary> _map = new(); - private readonly HashSet _immutable = new(); - - public bool ContainsState(ISelectionSet selectionSet) - { - var taken = false; - Monitor.Enter(_map, ref taken); - - try - { - return _map.ContainsKey(selectionSet); - } - finally - { - if (taken) - { - Monitor.Exit(_map); - } - } - } - - public bool ContainsState(ISelectionSet[] selectionSets) - { - var taken = false; - Monitor.Enter(_map, ref taken); - - try - { - ref var start = ref MemoryMarshal.GetArrayDataReference(selectionSets); - ref var end = ref Unsafe.Add(ref start, selectionSets.Length); - - while (Unsafe.IsAddressLessThan(ref start, ref end)) - { - if (_map.ContainsKey(start)) - { - return true; - } - - start = ref Unsafe.Add(ref start, 1)!; - } - } - finally - { - if (taken) - { - Monitor.Exit(_map); - } - } - - return false; - } - - public bool TryGetState( - ISelectionSet selectionSet, - [NotNullWhen(true)] out IReadOnlyList? values) - { - var taken = false; - Monitor.Enter(_map, ref taken); - - try - { - // We mark a value immutable on first read. - // - // After we accessed the first time the state of a selection set its no longer allowed - // to mutate it. - // - // The query plan should actually be ordered in a way that there are no mutations after - // the state is being read from nodes. - _immutable.Add(selectionSet); - - if (_map.TryGetValue(selectionSet, out var local)) - { - values = local; - return true; - } - else - { - values = null; - return false; - } - } - finally - { - if (taken) - { - Monitor.Exit(_map); - } - } - } - - public void TryRegisterState( + public ExecutionState( ISelectionSet selectionSet, - ObjectResult result, - IReadOnlyList exportKeys, - SelectionData parentData) - { - var taken = false; - List? states; - SelectionSetState? state; - Monitor.Enter(_map, ref taken); - - try - { - if (_immutable.Contains(selectionSet)) - { - return; - } - - state = new SelectionSetState(selectionSet, result, exportKeys) - { - SelectionSetData = { [0] = parentData } - }; - - if (!_map.TryGetValue(state.SelectionSet, out states)) - { - var temp = new List { state }; - _map.Add(state.SelectionSet, temp); - } - } - finally - { - if (taken) - { - Monitor.Exit(_map); - } - } - - AddState(states, state); - } - - public void RegisterState(SelectionSetState state) + ObjectResult selectionSetResult, + IReadOnlyList exportKeys) { - var taken = false; - List? states; - Monitor.Enter(_map, ref taken); - - try - { - if (_immutable.Contains(state.SelectionSet)) - { - throw new InvalidOperationException( - string.Format(ExecutionState_RegisterState_StateImmutable, state.SelectionSet.Id)); - } - - if (!_map.TryGetValue(state.SelectionSet, out states)) - { - var temp = new List { state }; - _map.Add(state.SelectionSet, temp); - } - } - finally - { - if (taken) - { - Monitor.Exit(_map); - } - } - - AddState(states, state); + SelectionSet = selectionSet; + SelectionSetResult = selectionSetResult; + SelectionSetData = new SelectionData[selectionSet.Selections.Count]; + ExportKeys = exportKeys; } - - private static void AddState(List? states, SelectionSetState state) - { - if (states is null) - { - return; - } - - var taken = false; - Monitor.Enter(states, ref taken); - try - { - states.Add(state); - } - finally - { - if (taken) - { - Monitor.Exit(states); - } - } - } + /// + /// Gets a collection of exported variable values that + /// are passed on to the next query plan node. + /// + public Dictionary VariableValues { get; } = new(); + + /// + /// Gets a list of keys representing the state that is being + /// exported while processing this work item. + /// + public IReadOnlyList ExportKeys { get; } + + /// + /// Gets the selection set that is being executed. + /// + public ISelectionSet SelectionSet { get; } + + /// + /// Gets the selection set data that was collected during execution. + /// + public SelectionData[] SelectionSetData { get; } + + /// + /// Gets the completed selection set result. + /// + public ObjectResult SelectionSetResult { get; } + + /// + /// Gets a flag that indicates if the work item has been initialized. + /// + /// + public bool IsInitialized { get; set; } } diff --git a/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs b/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs index 054f884c0d9..5e8913bfe9e 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs @@ -24,12 +24,12 @@ internal static class ExecutorUtils public static void ComposeResult( FusionExecutionContext context, - SelectionSetState selectionSetState) + ExecutionState executionState) => ComposeResult( context, - (SelectionSet)selectionSetState.SelectionSet, - selectionSetState.SelectionSetData, - selectionSetState.SelectionSetResult); + (SelectionSet)executionState.SelectionSet, + executionState.SelectionSetData, + executionState.SelectionSetResult); private static void ComposeResult( FusionExecutionContext context, @@ -307,7 +307,7 @@ private static void ComposeResult( type = context.Schema.GetType(typeMetadata.Name); } - var selectionSet = (SelectionSet)context.Operation.GetSelectionSet(selection, type); + var selectionSet = Unsafe.As(context.Operation.GetSelectionSet(selection, type)); var selectionCount = selectionSet.Selections.Count; var result = context.Result.RentObject(selectionCount); @@ -446,39 +446,39 @@ public static void ExtractSelectionResults( } } - public static void TryInitializeWorkItem(QueryPlan queryPlan, SelectionSetState selectionSetState) + public static void TryInitializeExecutionState(QueryPlan queryPlan, ExecutionState executionState) { - if (selectionSetState.IsInitialized) + if (executionState.IsInitialized) { return; } // capture the partial result available - var partialResult = selectionSetState.SelectionSetData[0]; + var partialResult = executionState.SelectionSetData[0]; // if we have a partial result available lets unwrap it. if (partialResult.HasValue) { // first we need to erase the partial result from the array so that its not // combined into the result creation. - selectionSetState.SelectionSetData[0] = default; + executionState.SelectionSetData[0] = default; // next we will unwrap the results. ExtractSelectionResults( partialResult, - (SelectionSet)selectionSetState.SelectionSet, - selectionSetState.SelectionSetData); + (SelectionSet)executionState.SelectionSet, + executionState.SelectionSetData); // last we will check if there are any exports for this selection-set. ExtractVariables( partialResult, queryPlan, - selectionSetState.SelectionSet, - selectionSetState.ExportKeys, - selectionSetState.VariableValues); + executionState.SelectionSet, + executionState.ExportKeys, + executionState.VariableValues); } - selectionSetState.IsInitialized = true; + executionState.IsInitialized = true; } public static void ExtractErrors( diff --git a/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs b/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs index cd442af8990..262d5215a83 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs @@ -55,7 +55,7 @@ public FusionExecutionContext( /// /// Gets the execution state. /// - public ExecutionState State { get; } = new(); + public RequestState State { get; } = new(); /// /// Gets access to the underlying operation context. @@ -108,7 +108,7 @@ public async Task ExecuteAsync( return await client.ExecuteAsync(request, cancellationToken).ConfigureAwait(false); } - public async Task> ExecuteAsync( + public async Task ExecuteAsync( string subgraphName, IReadOnlyList requests, CancellationToken cancellationToken) diff --git a/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs b/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs index f0d59165b37..2394b29ba0a 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs @@ -4,7 +4,7 @@ namespace HotChocolate.Fusion.Execution; internal static class FusionContextExtensions { - public static SelectionSetState RegisterState( + public static ExecutionState RegisterState( this FusionExecutionContext context, ISelectionSet selectionSet, ObjectResult result, @@ -12,7 +12,7 @@ public static SelectionSetState RegisterState( { var exportKeys = context.QueryPlan.GetExportKeys(selectionSet); - var workItem = new SelectionSetState(selectionSet, result, exportKeys) + var workItem = new ExecutionState(selectionSet, result, exportKeys) { SelectionSetData = { [0] = parentData } }; diff --git a/src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs b/src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs new file mode 100644 index 00000000000..684fea80321 --- /dev/null +++ b/src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs @@ -0,0 +1,194 @@ +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using HotChocolate.Execution.Processing; +using static HotChocolate.Fusion.FusionResources; + +namespace HotChocolate.Fusion.Execution; + +internal sealed class RequestState +{ + private readonly Dictionary> _map = new(); + private readonly HashSet _immutable = new(); + + public bool ContainsState(ISelectionSet selectionSet) + { + var taken = false; + Monitor.Enter(_map, ref taken); + + try + { + return _map.ContainsKey(selectionSet); + } + finally + { + if (taken) + { + Monitor.Exit(_map); + } + } + } + + public bool ContainsState(SelectionSet[] selectionSets) + { + var taken = false; + Monitor.Enter(_map, ref taken); + + try + { + ref var start = ref MemoryMarshal.GetArrayDataReference(selectionSets); + ref var end = ref Unsafe.Add(ref start, selectionSets.Length); + + while (Unsafe.IsAddressLessThan(ref start, ref end)) + { + if (_map.ContainsKey(start)) + { + return true; + } + + start = ref Unsafe.Add(ref start, 1)!; + } + } + finally + { + if (taken) + { + Monitor.Exit(_map); + } + } + + return false; + } + + public bool TryGetState( + ISelectionSet selectionSet, + [NotNullWhen(true)] out List? values) + { + var taken = false; + Monitor.Enter(_map, ref taken); + + try + { + // We mark a value immutable on first read. + // + // After we accessed the first time the state of a selection set its no longer allowed + // to mutate it. + // + // The query plan should actually be ordered in a way that there are no mutations after + // the state is being read from nodes. + _immutable.Add(selectionSet); + + if (_map.TryGetValue(selectionSet, out var local)) + { + values = local; + return true; + } + else + { + values = null; + return false; + } + } + finally + { + if (taken) + { + Monitor.Exit(_map); + } + } + } + + public void TryRegisterState( + ISelectionSet selectionSet, + ObjectResult result, + IReadOnlyList exportKeys, + SelectionData parentData) + { + var taken = false; + List? states; + ExecutionState? state; + Monitor.Enter(_map, ref taken); + + try + { + if (_immutable.Contains(selectionSet)) + { + return; + } + + state = new ExecutionState(selectionSet, result, exportKeys) + { + SelectionSetData = { [0] = parentData } + }; + + if (!_map.TryGetValue(state.SelectionSet, out states)) + { + var temp = new List { state }; + _map.Add(state.SelectionSet, temp); + } + } + finally + { + if (taken) + { + Monitor.Exit(_map); + } + } + + AddState(states, state); + } + + public void RegisterState(ExecutionState state) + { + var taken = false; + List? states; + Monitor.Enter(_map, ref taken); + + try + { + if (_immutable.Contains(state.SelectionSet)) + { + throw new InvalidOperationException( + string.Format(ExecutionState_RegisterState_StateImmutable, state.SelectionSet.Id)); + } + + if (!_map.TryGetValue(state.SelectionSet, out states)) + { + var temp = new List { state }; + _map.Add(state.SelectionSet, temp); + } + } + finally + { + if (taken) + { + Monitor.Exit(_map); + } + } + + AddState(states, state); + } + + private static void AddState(List? states, ExecutionState state) + { + if (states is null) + { + return; + } + + var taken = false; + Monitor.Enter(states, ref taken); + + try + { + states.Add(state); + } + finally + { + if (taken) + { + Monitor.Exit(states); + } + } + } +} diff --git a/src/HotChocolate/Fusion/src/Core/Execution/SelectionSetState.cs b/src/HotChocolate/Fusion/src/Core/Execution/SelectionSetState.cs deleted file mode 100644 index 0d1215377c9..00000000000 --- a/src/HotChocolate/Fusion/src/Core/Execution/SelectionSetState.cs +++ /dev/null @@ -1,55 +0,0 @@ -using HotChocolate.Execution.Processing; -using HotChocolate.Language; - -namespace HotChocolate.Fusion.Execution; - -/// -/// Represents the query plan state for a single selection set. -/// This working state can be shared between nodes of a query plan. -/// -internal sealed class SelectionSetState // SelectionSetState -{ - public SelectionSetState( - ISelectionSet selectionSet, - ObjectResult selectionSetResult, - IReadOnlyList exportKeys) - { - SelectionSet = selectionSet; - SelectionSetResult = selectionSetResult; - SelectionSetData = new SelectionData[selectionSet.Selections.Count]; - ExportKeys = exportKeys; - } - - /// - /// Gets a collection of exported variable values that - /// are passed on to the next query plan node. - /// - public Dictionary VariableValues { get; } = new(); - - /// - /// Gets a list of keys representing the state that is being - /// exported while processing this work item. - /// - public IReadOnlyList ExportKeys { get; } - - /// - /// Gets the selection set that is being executed. - /// - public ISelectionSet SelectionSet { get; } - - /// - /// Gets the selection set data that was collected during execution. - /// - public SelectionData[] SelectionSetData { get; } - - /// - /// Gets the completed selection set result. - /// - public ObjectResult SelectionSetResult { get; } - - /// - /// Gets a flag that indicates if the work item has been initialized. - /// - /// - public bool IsInitialized { get; set; } -} diff --git a/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj b/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj index 5c0fe994e08..896941fb02c 100644 --- a/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj +++ b/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj @@ -50,6 +50,9 @@ ResolverDefinition.cs + + ResolverNodeBase.cs + diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs index 71040b5d417..4b036a682e2 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs @@ -135,15 +135,17 @@ private Resolve CreateResolveNode( context.RegisterSelectionSet(selectionSet); - return new Resolve( - context.NextNodeId(), + var config = new ResolverNodeBase.Config( executionStep.SubgraphName, request.Document, selectionSet, - executionStep.Variables.Values.ToArray(), + context.Exports.GetExportKeys(executionStep), + executionStep.Variables.Values, + context.ForwardedVariables.Select(t => t.Variable.Name.Value), request.Path, - context.ForwardedVariables.Select(t => t.Variable.Name.Value).ToArray(), DetermineTransportFeatures(context)); + + return new Resolve(context.NextNodeId(), config); } private TransportFeatures DetermineTransportFeatures( @@ -211,16 +213,18 @@ private Resolve CreateResolveNodeNode( executionStep.SelectionSetTypeMetadata.Name); context.RegisterSelectionSet(selectionSet); - - return new Resolve( - context.NextNodeId(), + + var config = new ResolverNodeBase.Config( executionStep.SelectEntityStep.SubgraphName, requestDocument, selectionSet, - executionStep.SelectEntityStep.Variables.Values.ToArray(), + context.Exports.GetExportKeys(executionStep), + executionStep.SelectEntityStep.Variables.Values, + context.ForwardedVariables.Select(t => t.Variable.Name.Value), path, - context.ForwardedVariables.Select(t => t.Variable.Name.Value).ToArray(), DetermineTransportFeatures(context)); + + return new Resolve(context.NextNodeId(), config); } private ResolveByKeyBatch CreateResolveByKeyBatchNode( @@ -255,17 +259,18 @@ private ResolveByKeyBatch CreateResolveByKeyBatchNode( argumentTypes = temp; } - - return new ResolveByKeyBatch( - context.NextNodeId(), + + var config = new ResolverNodeBase.Config( executionStep.SubgraphName, request.Document, selectionSet, - executionStep.Variables.Values.ToArray(), + context.Exports.GetExportKeys(executionStep), + executionStep.Variables.Values, + context.ForwardedVariables.Select(t => t.Variable.Name.Value), request.Path, - argumentTypes, - context.ForwardedVariables.Select(t => t.Variable.Name.Value).ToArray(), DetermineTransportFeatures(context)); + + return new ResolveByKeyBatch(context.NextNodeId(), config, argumentTypes); } private Subscribe CreateSubscribeNode( diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs index 41303e83734..6d1491b44dc 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs @@ -23,7 +23,7 @@ public string Register( FieldVariableDefinition variableDefinition, ExecutionStep providingExecutionStep) { - if(_stateKeyLookup.TryGetValue((selectionSet, variableDefinition.Name), out var stateKey)) + if (_stateKeyLookup.TryGetValue((selectionSet, variableDefinition.Name), out var stateKey)) { return stateKey; } @@ -123,4 +123,15 @@ public IEnumerable GetExportSelections( } } } -} + + public IEnumerable GetExportKeys(ExecutionStep executionStep) + { + foreach (var exportDefinition in _exports) + { + if (ReferenceEquals(exportDefinition.ExecutionStep, executionStep)) + { + yield return exportDefinition.StateKey; + } + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs index 88132b63827..5d1d2089a7d 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs @@ -4,26 +4,23 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution; using static HotChocolate.Fusion.Execution.ExecutorUtils; +using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; internal sealed class Compose : QueryPlanNode { - private readonly ISelectionSet[] _selectionSets; + private readonly SelectionSet[] _selectionSets; public Compose(int id, Resolve resolve) : this(id, new[] { resolve.SelectionSet }) { } - public Compose(int id, ISelectionSet selectionSet) + public Compose(int id, SelectionSet selectionSet) : this(id, new[] { selectionSet }) { } - public Compose(int id, IReadOnlyList selectionSets) : base(id) + public Compose(int id, IReadOnlyList selectionSets) : base(id) { - if (selectionSets is null) - { - throw new ArgumentNullException(nameof(selectionSets)); - } - + ArgumentNullException.ThrowIfNull(selectionSets); _selectionSets = selectionSets.Distinct().OrderBy(t => t.Id).ToArray(); } @@ -31,7 +28,7 @@ public Compose(int id, IReadOnlyList selectionSets) : base(id) protected override Task OnExecuteAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { if (_selectionSets.Length == 1) @@ -68,7 +65,7 @@ protected override Task OnExecuteAsync( protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { if (_selectionSets.Length == 1) @@ -89,7 +86,7 @@ protected override async Task OnExecuteNodesAsync( protected override void FormatProperties(Utf8JsonWriter writer) { - writer.WritePropertyName("selectionSetIds"); + writer.WritePropertyName(SelectionSetIdsProp); writer.WriteStartArray(); foreach (var selectionSet in _selectionSets) @@ -99,4 +96,4 @@ protected override void FormatProperties(Utf8JsonWriter writer) writer.WriteEndArray(); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs index c5c8c8a4de7..409f7f8cc92 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs @@ -16,7 +16,7 @@ public If(int id) : base(id) protected override Task OnExecuteNodesAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { var contextData = (ConcurrentDictionary)context.OperationContext.ContextData; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs index f0b95d8447c..e62f0936691 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs @@ -21,7 +21,7 @@ public Introspect(int id, ISelectionSet selectionSet) : base(id) protected override async Task OnExecuteAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { if (state.TryGetState(_selectionSet, out var values)) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs index a75b635eeff..e590d16f4df 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs @@ -10,7 +10,7 @@ public Parallel(int id) : base(id) { } protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { var tasks = new Task[Nodes.Count]; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs index 03279217421..09b053c6710 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs @@ -37,13 +37,13 @@ internal async Task ExecuteAsync( protected virtual Task OnExecuteAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) => Task.CompletedTask; protected virtual async Task OnExecuteNodesAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { for (var i = 0; i < _nodes.Count; i++) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ReformatVariableRewriter.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ReformatVariableRewriter.cs new file mode 100644 index 00000000000..1c9bf753fea --- /dev/null +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ReformatVariableRewriter.cs @@ -0,0 +1,33 @@ +using HotChocolate.Language; +using HotChocolate.Language.Visitors; +using HotChocolate.Transport.Http; +using HotChocolate.Types; + +namespace HotChocolate.Fusion.Planning; + +internal sealed class ReformatVariableRewriter : SyntaxRewriter, ISyntaxVisitorContext +{ + private static readonly ReformatVariableRewriter _instance = new(); + + public static IValueNode Rewrite(IValueNode node) + { + if (_instance.Rewrite(node, _instance) is IValueNode rewritten) + { + return rewritten; + } + + return NullValueNode.Default; + } + + protected override IValueNode? RewriteCustomValue(IValueNode node, ReformatVariableRewriter context) + { + if (node is FileValueNode fileValueNode) + { + return new FileReferenceNode( + fileValueNode.Value.OpenReadStream, + fileValueNode.Value.Name); + } + + return node; + } +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs index 89fdd630aed..63f53c33b15 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs @@ -1,7 +1,7 @@ -using HotChocolate.Execution.Processing; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using HotChocolate.Fusion.Clients; using HotChocolate.Fusion.Execution; -using HotChocolate.Language; using static HotChocolate.Fusion.Execution.ExecutorUtils; namespace HotChocolate.Fusion.Planning; @@ -17,39 +17,11 @@ internal sealed class Resolve : ResolverNodeBase /// /// The unique id of this node. /// - /// - /// The name of the subgraph on which this request handler executes. + /// + /// Gets the resolver configuration. /// - /// - /// The GraphQL request document. - /// - /// - /// The selection set for which this request provides a patch. - /// - /// - /// The variables that this request handler requires to create a request. - /// - /// - /// The path to the data that this request handler needs to extract. - /// - /// - /// The variables that this request handler forwards to the subgraph. - /// - /// - /// The transport features that are required by this node. - /// - public Resolve( - int id, - string subgraphName, - DocumentNode document, - ISelectionSet selectionSet, - IReadOnlyList requires, - IReadOnlyList path, - IReadOnlyList forwardedVariables, - TransportFeatures transportFeatures) - : base(id, subgraphName, document, selectionSet, requires, path, forwardedVariables, transportFeatures) - { - } + public Resolve(int id, Config config) + : base(id, config) { } /// /// Gets the kind of this node. @@ -70,67 +42,27 @@ public Resolve( /// protected override async Task OnExecuteAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { - if (state.TryGetState(SelectionSet, out var workItems)) + if (state.TryGetState(SelectionSet, out var executionState)) { - var schemaName = SubgraphName; - var requests = new SubgraphGraphQLRequest[workItems.Count]; + var requests = new SubgraphGraphQLRequest[executionState.Count]; - // first we will create a request for all of our work items. - for (var i = 0; i < workItems.Count; i++) - { - var workItem = workItems[i]; - TryInitializeWorkItem(context.QueryPlan, workItem); - requests[i] = CreateRequest( - context.OperationContext.Variables, - workItem.VariableValues); - } + // first we will create request for all of our selection sets. + InitializeRequests(context, executionState, requests); // once we have the requests, we will enqueue them for execution with the execution engine. // the execution engine will batch these requests if possible. - var responses = await context.ExecuteAsync( - schemaName, - requests, - cancellationToken) - .ConfigureAwait(false); + var responses = await context.ExecuteAsync(SubgraphName, requests, cancellationToken).ConfigureAwait(false); // before we extract the data from the responses we will enqueue the responses // for cleanup so that the memory can be released at the end of the execution. // Since we are not fully deserializing the responses we cannot release the memory here // but need to wait until the transport layer is finished and disposes the result. - context.Result.RegisterForCleanup( - responses, - r => - { - for (var i = 0; i < r.Count; i++) - { - r[i].Dispose(); - } - return default!; - }); - - for (var i = 0; i < requests.Length; i++) - { - var response = responses[i]; - var workItem = workItems[i]; - - var data = UnwrapResult(response); - var selectionSet = workItem.SelectionSet; - var selectionResults = workItem.SelectionSetData; - var exportKeys = workItem.ExportKeys; - var variableValues = workItem.VariableValues; - - ExtractErrors(context.Result, response.Errors, context.ShowDebugInfo); - - // we extract the selection data from the request and add it to the - // workItem results. - ExtractSelectionResults(SelectionSet, schemaName, data, selectionResults); - - // next we need to extract any variables that we need for followup requests. - ExtractVariables(data, context.QueryPlan, selectionSet, exportKeys, variableValues); - } + context.Result.RegisterForCleanup(responses, ReturnResults); + + ProcessResponses(context, executionState, requests, responses, SubgraphName); } } @@ -148,7 +80,7 @@ protected override async Task OnExecuteAsync( /// protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { if (state.ContainsState(SelectionSet)) @@ -156,4 +88,58 @@ protected override async Task OnExecuteNodesAsync( await base.OnExecuteNodesAsync(context, state, cancellationToken).ConfigureAwait(false); } } -} + + private void InitializeRequests( + FusionExecutionContext context, + List executionState, + SubgraphGraphQLRequest[] requests) + { + ref var state = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(executionState)); + ref var request = ref MemoryMarshal.GetArrayDataReference(requests); + ref var end = ref Unsafe.Add(ref state, executionState.Count); + + while (Unsafe.IsAddressLessThan(ref state, ref end)) + { + TryInitializeExecutionState(context.QueryPlan, state); + request = CreateRequest(context.OperationContext.Variables, state.VariableValues); + + state = ref Unsafe.Add(ref state, 1); + request = ref Unsafe.Add(ref request, 1); + } + } + + private void ProcessResponses( + FusionExecutionContext context, + List executionStates, + SubgraphGraphQLRequest[] requests, + GraphQLResponse[] responses, + string subgraphName) + { + ref var state = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(executionStates)); + ref var request = ref MemoryMarshal.GetArrayDataReference(requests); + ref var response = ref MemoryMarshal.GetArrayDataReference(responses); + ref var end = ref Unsafe.Add(ref state, executionStates.Count); + + while (Unsafe.IsAddressLessThan(ref state, ref end)) + { + var data = UnwrapResult(response); + var selectionSet = state.SelectionSet; + var selectionResults = state.SelectionSetData; + var exportKeys = state.ExportKeys; + var variableValues = state.VariableValues; + + ExtractErrors(context.Result, response.Errors, context.ShowDebugInfo); + + // we extract the selection data from the request and add it to the + // workItem results. + ExtractSelectionResults(SelectionSet, subgraphName, data, selectionResults); + + // next we need to extract any variables that we need for followup requests. + ExtractVariables(data, context.QueryPlan, selectionSet, exportKeys, variableValues); + + state = ref Unsafe.Add(ref state, 1); + request = ref Unsafe.Add(ref request, 1); + response = ref Unsafe.Add(ref response, 1); + } + } +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs index b73c009e656..a1a278f4723 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs @@ -1,4 +1,7 @@ +using System.Collections.Frozen; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; using System.Text.Json; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; @@ -10,89 +13,46 @@ namespace HotChocolate.Fusion.Planning; internal sealed class ResolveByKeyBatch : ResolverNodeBase { - private readonly IReadOnlyList _path; - - public ResolveByKeyBatch( - int id, - string subgraphName, - DocumentNode document, - ISelectionSet selectionSet, - IReadOnlyList requires, - IReadOnlyList path, - IReadOnlyDictionary argumentTypes, - IReadOnlyList forwardedVariables, - TransportFeatures transportFeatures) - : base(id, subgraphName, document, selectionSet, requires, path, forwardedVariables, transportFeatures) + private readonly Dictionary _argumentTypes; + + public ResolveByKeyBatch(int id, Config config, IReadOnlyDictionary argumentTypes) + : base(id, config) { - ArgumentTypes = argumentTypes; - _path = path; + _argumentTypes = new Dictionary(argumentTypes, StringComparer.Ordinal); } public override QueryPlanNodeKind Kind => QueryPlanNodeKind.ResolveByKeyBatch; - - /// - /// Gets the type lookup of resolver arguments. - /// - public IReadOnlyDictionary ArgumentTypes { get; } - + protected override async Task OnExecuteAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { - if (state.TryGetState(SelectionSet, out var originalWorkItems)) + if (state.TryGetState(SelectionSet, out var executionState)) { - for (var i = 0; i < originalWorkItems.Count; i++) - { - TryInitializeWorkItem(context.QueryPlan, originalWorkItems[i]); - } + InitializeRequests(context, executionState); - var workItems = CreateBatchWorkItem(originalWorkItems, Requires); - var subgraphName = SubgraphName; - var firstWorkItem = workItems[0]; + var batchExecutionState = CreateBatchBatchState(executionState, Requires); // Create the batch subgraph request. - var variableValues = BuildVariables(workItems); - var request = CreateRequest( - context.OperationContext.Variables, - variableValues); + var variableValues = BuildVariables(batchExecutionState); + var request = CreateRequest(context.OperationContext.Variables, variableValues); // Once we have the batch request, we will enqueue it for execution with // the execution engine. - var response = await context.ExecuteAsync( - subgraphName, - request, - cancellationToken) - .ConfigureAwait(false); + var response = await context.ExecuteAsync(SubgraphName, request, cancellationToken).ConfigureAwait(false); // Before we extract the data from the responses we will enqueue the responses // for cleanup so that the memory can be released at the end of the execution. - context.Result.RegisterForCleanup( - response, - r => - { - r.Dispose(); - return default!; - }); - - ExtractErrors(context.Result, response.Errors, context.ShowDebugInfo); - var result = UnwrapResult(response, Requires); + context.Result.RegisterForCleanup(response, ReturnResult); - for (var i = 0; i < workItems.Length; i++) - { - var workItem = workItems[i]; - if (result.TryGetValue(workItem.Key, out var workItemData)) - { - ExtractSelectionResults(SelectionSet, subgraphName, workItemData, workItem.SelectionResults); - ExtractVariables(workItemData, context.QueryPlan, SelectionSet, firstWorkItem.ExportKeys, workItem.VariableValues); - } - } + ProcessResult(context, response, batchExecutionState); } } protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { if (state.ContainsState(SelectionSet)) @@ -100,19 +60,57 @@ protected override async Task OnExecuteNodesAsync( await base.OnExecuteNodesAsync(context, state, cancellationToken).ConfigureAwait(false); } } + + private static void InitializeRequests(FusionExecutionContext context, List executionState) + { + ref var state = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(executionState)); + ref var end = ref Unsafe.Add(ref state, executionState.Count); + + while (Unsafe.IsAddressLessThan(ref state, ref end)) + { + TryInitializeExecutionState(context.QueryPlan, state); + } + } - private Dictionary BuildVariables(BatchWorkItem[] workItems) + private void ProcessResult( + FusionExecutionContext context, + GraphQLResponse response, + BatchExecutionState[] batchExecutionState) { - if (workItems.Length == 1) + var first = batchExecutionState[0]; + + ExtractErrors(context.Result, response.Errors, context.ShowDebugInfo); + var result = UnwrapResult(response, Requires); + + ref var batchState = ref MemoryMarshal.GetArrayDataReference(batchExecutionState); + ref var end = ref Unsafe.Add(ref batchState, batchExecutionState.Length); + + while (Unsafe.IsAddressLessThan(ref batchState, ref end)) { - return workItems[0].VariableValues; + if (result.TryGetValue(batchState.Key, out var workItemData)) + { + ExtractSelectionResults(SelectionSet, SubgraphName, workItemData, batchState.SelectionResults); + ExtractVariables(workItemData, context.QueryPlan, SelectionSet, first.ExportKeys, first.VariableValues); + } + + batchState = ref Unsafe.Add(ref batchState, 1); + } + } + + private static Dictionary BuildVariables( + BatchExecutionState[] batchExecutionState, + Dictionary argumentTypes) + { + if (batchExecutionState.Length == 1) + { + return batchExecutionState[0].VariableValues; } var variableValues = new Dictionary(); - var uniqueWorkItems = new List(); + var uniqueWorkItems = new List(); var processed = new HashSet(); - foreach (var workItem in workItems) + foreach (var workItem in batchExecutionState) { if (processed.Add(workItem.Key)) { @@ -120,9 +118,9 @@ private Dictionary BuildVariables(BatchWorkItem[] workItems) } } - foreach (var key in workItems[0].VariableValues.Keys) + foreach (var key in batchExecutionState[0].VariableValues.Keys) { - var expectedType = ArgumentTypes[key]; + var expectedType = argumentTypes[key]; if (expectedType.IsListType()) { @@ -140,7 +138,7 @@ private Dictionary BuildVariables(BatchWorkItem[] workItems) } else { - if (workItems[0].VariableValues.TryGetValue(key, out var variableValue)) + if (batchExecutionState[0].VariableValues.TryGetValue(key, out var variableValue)) { variableValues.Add(key, variableValue); } @@ -155,13 +153,14 @@ private Dictionary UnwrapResult( IReadOnlyList exportKeys) { var data = response.Data; + var path = Path; if (data.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) { return new Dictionary(); } - if (_path.Count > 0) + if (path.Length > 0) { data = LiftData(); } @@ -228,108 +227,48 @@ JsonElement LiftData() } } - private static BatchWorkItem[] CreateBatchWorkItem( - IReadOnlyList workItems, - IReadOnlyList requirements) + private static BatchExecutionState[] CreateBatchBatchState(List executionState, string[] requires) { - var batchWorkItems = new BatchWorkItem[workItems.Count]; + var batchExecutionState = new BatchExecutionState[executionState.Count]; + + ref var state = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(executionState)); + ref var batchState = ref MemoryMarshal.GetArrayDataReference(batchExecutionState); + ref var end = ref Unsafe.Add(ref state, executionState.Count); - if (requirements.Count == 1) + if (requires.Length == 1) { - for (var i = 0; i < workItems.Count; i++) + while (Unsafe.IsAddressLessThan(ref state, ref end)) { - var workItem = workItems[i]; - var key = FormatKeyValue(workItem.VariableValues[requirements[0]]); - batchWorkItems[i] = new BatchWorkItem(key, workItem); + var key = FormatKeyValue(state.VariableValues[requires[0]]); + batchState = new BatchExecutionState(key, state); + + state = ref Unsafe.Add(ref state, 1); + batchState = ref Unsafe.Add(ref batchState, 1); } } else { - for (var i = 0; i < workItems.Count; i++) + var keyBuilder = new StringBuilder(); + + while (Unsafe.IsAddressLessThan(ref state, ref end)) { - var workItem = workItems[i]; - var key = string.Empty; + ref var key = ref MemoryMarshal.GetArrayDataReference(requires); + ref var keyEnd = ref Unsafe.Add(ref key, requires.Length); - for (var j = 0; j < requirements.Count; j++) + while (Unsafe.IsAddressLessThan(ref key, ref keyEnd)) { - var requirement = requirements[j]; - var value = FormatKeyValue(workItem.VariableValues[requirement]); - key += value; + keyBuilder.Append(FormatKeyValue(state.VariableValues[key])); + key = ref Unsafe.Add(ref key, 1); } - batchWorkItems[i] = new BatchWorkItem(key, workItem); - } - } - - return batchWorkItems; - } - - /// - /// Formats the properties of this query plan node in order to create a JSON representation. - /// - /// - /// The writer that is used to write the JSON representation. - /// - protected override void FormatProperties(Utf8JsonWriter writer) - { - writer.WriteString("subgraph", SubgraphName); - writer.WriteString("document", Document); - writer.WriteNumber("selectionSetId", SelectionSet.Id); - - if (ArgumentTypes.Count > 0) - { - writer.WritePropertyName("argumentTypes"); - writer.WriteStartArray(); + batchState = new BatchExecutionState(key, state); - foreach (var (argument, type) in ArgumentTypes) - { - writer.WriteStartObject(); - writer.WriteString("argument", argument); - writer.WriteString("type", type.ToString(false)); - writer.WriteEndObject(); + state = ref Unsafe.Add(ref state, 1); + batchState = ref Unsafe.Add(ref batchState, 1); } - writer.WriteEndArray(); } - if (Path.Count > 0) - { - writer.WritePropertyName("path"); - writer.WriteStartArray(); - - foreach (var path in Path) - { - writer.WriteStringValue(path); - } - writer.WriteEndArray(); - } - - if (Requires.Count > 0) - { - writer.WritePropertyName("requires"); - writer.WriteStartArray(); - - foreach (var requirement in Requires) - { - writer.WriteStartObject(); - writer.WriteString("variable", requirement); - writer.WriteEndObject(); - } - writer.WriteEndArray(); - } - - if (ForwardedVariables.Count > 0) - { - writer.WritePropertyName("forwardedVariables"); - writer.WriteStartArray(); - - foreach (var variable in ForwardedVariables) - { - writer.WriteStartObject(); - writer.WriteString("variable", variable); - writer.WriteEndObject(); - } - writer.WriteEndArray(); - } + return batchExecutionState; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -357,16 +296,16 @@ private static string FormatKeyValue(IValueNode element) _ => throw new NotSupportedException(), }; - private readonly struct BatchWorkItem + private readonly struct BatchExecutionState { - public BatchWorkItem( + public BatchExecutionState( string batchKey, - SelectionSetState selectionSetState) + ExecutionState executionState) { Key = batchKey; - VariableValues = selectionSetState.VariableValues; - ExportKeys = selectionSetState.ExportKeys; - SelectionResults = selectionSetState.SelectionSetData; + VariableValues = executionState.VariableValues; + ExportKeys = executionState.ExportKeys; + SelectionResults = executionState.SelectionSetData; } public string Key { get; } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs index 81893324cf8..e3d09aa0f82 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs @@ -23,7 +23,7 @@ public ResolveNode(int id, ISelection selection) : base(id) protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, - ExecutionState state, + RequestState state, CancellationToken cancellationToken) { var variables = context.OperationContext.Variables; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs new file mode 100644 index 00000000000..d22cf816df5 --- /dev/null +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs @@ -0,0 +1,130 @@ +using System.Buffers; +using System.Runtime.CompilerServices; +using HotChocolate.Execution.Processing; +using HotChocolate.Fusion.Clients; +using HotChocolate.Language; + +namespace HotChocolate.Fusion.Planning; + +internal abstract partial class ResolverNodeBase +{ + /// + /// The resolver configuration. + /// + internal readonly ref struct Config + { + private readonly bool _isInitialized; + + /// + /// Initializes a new instance of . + /// + /// + /// The name of the subgraph on which this request handler executes. + /// + /// + /// The GraphQL request document. + /// + /// + /// The selection set for which this request provides a patch. + /// + /// + /// The variables that this resolver node will provide. + /// + /// + /// The variables that this request handler requires to create a request. + /// + /// + /// The variables that this request handler forwards to the subgraph. + /// + /// + /// The path to the data that this request handler needs to extract. + /// + /// + /// The transport features that are required by this node. + /// + public Config( + string subgraphName, + DocumentNode document, + ISelectionSet selectionSet, + IEnumerable provides, + IEnumerable requires, + IEnumerable forwardedVariables, + IReadOnlyList path, + TransportFeatures transportFeatures) + { + string[]? buffer = null; + var usedCapacity = 0; + + SubgraphName = subgraphName; + Document = document.ToString(false); + SelectionSet = Unsafe.As(selectionSet); + Provides = CollectionUtils.CopyToArray(provides, ref buffer, ref usedCapacity); + Requires = CollectionUtils.CopyToArray(requires, ref buffer, ref usedCapacity); + Path = CollectionUtils.CopyToArray(path); + ForwardedVariables = CollectionUtils.CopyToArray(forwardedVariables, ref buffer, ref usedCapacity); + TransportFeatures = transportFeatures; + + if (buffer is not null && usedCapacity > 0) + { + buffer.AsSpan().Slice(0, usedCapacity).Clear(); + ArrayPool.Shared.Return(buffer); + } + + _isInitialized = true; + } + + /// + /// Gets the schema name on which this request handler executes. + /// + public string SubgraphName { get; } + + /// + /// Gets the GraphQL request document. + /// + public string Document { get; } + + /// + /// Gets the selection set for which this request provides a patch. + /// + public SelectionSet SelectionSet { get; } + + /// + /// Gets the variables that this request handler requires to create a request. + /// + public string[] Provides { get; } + + /// + /// Gets the variables that this request handler requires to create a request. + /// + public string[] Requires { get; } + + /// + /// Gets the path to the data that this request handler needs to extract. + /// + public string[] Path { get; } + + /// + /// Gets the variables that this request handler forwards to the subgraph. + /// + public string[] ForwardedVariables { get; } + + /// + /// Gets the required transport features for this resolver node. + /// + public TransportFeatures TransportFeatures { get; } + + /// + /// Validates the configuration. + /// + /// + /// The ResolverNodeBase.Config is not initialized. + /// + public void ThrowIfNotInitialized() + { + if (!_isInitialized) + { + throw new ArgumentNullException("The ResolverNodeBase.Config is not initialized."); + } + } + } +} diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs index 89f0985570f..2051376c555 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs @@ -1,11 +1,11 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text.Json; using HotChocolate.Execution; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; using HotChocolate.Language; -using HotChocolate.Language.Visitors; -using HotChocolate.Transport.Http; -using HotChocolate.Types; +using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; @@ -13,86 +13,49 @@ namespace HotChocolate.Fusion.Planning; /// The resolver node is responsible for executing a GraphQL request on a subgraph. /// This represents the base class for various resolver node implementations. /// -internal abstract class ResolverNodeBase : QueryPlanNode +internal abstract partial class ResolverNodeBase : QueryPlanNode { + private readonly string _subgraphName; + private readonly string _document; + private readonly SelectionSet _selectionSet; + private readonly string[] _provides; + private readonly string[] _requires; + private readonly string[] _forwardedVariables; + private readonly string[] _path; + private readonly TransportFeatures _transportFeatures; + private readonly bool _hasDependencies; + /// /// Initializes a new instance of . /// /// /// The unique id of this node. /// - /// - /// The name of the subgraph on which this request handler executes. - /// - /// - /// The GraphQL request document. - /// - /// - /// The selection set for which this request provides a patch. - /// - /// - /// The variables that this request handler requires to create a request. - /// - /// - /// The path to the data that this request handler needs to extract. - /// - /// - /// The variables that this request handler forwards to the subgraph. - /// - /// - /// The transport features that are required by this node. + /// + /// Gets the resolver configuration. /// - protected ResolverNodeBase( - int id, - string subgraphName, - DocumentNode document, - ISelectionSet selectionSet, - IReadOnlyList requires, - IReadOnlyList path, - IReadOnlyList forwardedVariables, - TransportFeatures transportFeatures) + protected ResolverNodeBase(int id, Config config) : base(id) { - SubgraphName = subgraphName; - Document = document.ToString(false); - SelectionSet = (SelectionSet)selectionSet; - Requires = requires; - Path = path; - ForwardedVariables = forwardedVariables; - TransportFeatures = transportFeatures; + config.ThrowIfNotInitialized(); + _subgraphName = config.SubgraphName; + _document = config.Document; + _selectionSet = config.SelectionSet; + _provides = config.Provides; + _requires = config.Requires; + _forwardedVariables = config.ForwardedVariables; + _path = config.Path; + _transportFeatures = config.TransportFeatures; + _hasDependencies = _requires.Length > 0 || _forwardedVariables.Length > 0; } + + protected string SubgraphName => _subgraphName; + + protected internal SelectionSet SelectionSet => _selectionSet; + + protected string[] Requires => _requires; - /// - /// Gets the schema name on which this request handler executes. - /// - public string SubgraphName { get; } - - /// - /// Gets the GraphQL request document. - /// - public string Document { get; } - - /// - /// Gets the selection set for which this request provides a patch. - /// - public SelectionSet SelectionSet { get; } - - /// - /// Gets the variables that this request handler requires to create a request. - /// - public IReadOnlyList Requires { get; } - - /// - /// Gets the variables that this request handler forwards to the subgraph. - /// - public IReadOnlyList ForwardedVariables { get; } - - public TransportFeatures TransportFeatures { get; } - - /// - /// Gets the path to the data that this request handler needs to extract. - /// - public IReadOnlyList Path { get; } + protected string[] Path => _path; /// /// Creates a GraphQL request with the specified variable values. @@ -111,36 +74,52 @@ protected SubgraphGraphQLRequest CreateRequest( { ObjectValueNode? vars = null; - if (Requires.Count > 0 || ForwardedVariables.Count > 0) + if (_hasDependencies) { var fields = new List(); - foreach (var forwardedVariable in ForwardedVariables) + if (_forwardedVariables.Length > 0) { - if (variables.TryGetVariable(forwardedVariable, out var value) && - value is not null) + ref var forwardedVariable = ref MemoryMarshal.GetArrayDataReference(_forwardedVariables); + ref var end = ref Unsafe.Add(ref forwardedVariable, _forwardedVariables.Length); + + while (Unsafe.IsAddressLessThan(ref forwardedVariable, ref end)) { - value = ReformatVariableRewriter.Rewrite(value); - fields.Add(new ObjectFieldNode(forwardedVariable, value)); + if (variables.TryGetVariable(forwardedVariable, out var value) && + value is not null) + { + value = ReformatVariableRewriter.Rewrite(value); + fields.Add(new ObjectFieldNode(forwardedVariable, value)); + } + + forwardedVariable = ref Unsafe.Add(ref forwardedVariable, 1); } } - foreach (var requirement in Requires) + if (_requires.Length > 0) { - if (requirementValues.TryGetValue(requirement, out var value)) - { - fields.Add(new ObjectFieldNode(requirement, value)); - } - else + ref var requirement = ref MemoryMarshal.GetArrayDataReference(_requires); + ref var end = ref Unsafe.Add(ref requirement, _requires.Length); + + while (Unsafe.IsAddressLessThan(ref requirement, ref end)) { - throw ThrowHelper.Requirement_Is_Missing(requirement, nameof(requirementValues)); + if (requirementValues.TryGetValue(requirement, out var value)) + { + fields.Add(new ObjectFieldNode(requirement, value)); + } + else + { + throw ThrowHelper.Requirement_Is_Missing(requirement, nameof(requirementValues)); + } + + requirement = ref Unsafe.Add(ref requirement, 1); } } - - vars ??= new ObjectValueNode(fields); + + vars = new ObjectValueNode(fields); } - return new SubgraphGraphQLRequest(SubgraphName, Document, vars, null, TransportFeatures); + return new SubgraphGraphQLRequest(_subgraphName, _document, vars, null, _transportFeatures); } /// @@ -154,7 +133,7 @@ protected SubgraphGraphQLRequest CreateRequest( /// protected JsonElement UnwrapResult(GraphQLResponse response) { - if (Path.Count == 0) + if (_path.Length == 0) { return response.Data; } @@ -162,16 +141,20 @@ protected JsonElement UnwrapResult(GraphQLResponse response) if (response.Data.ValueKind is not JsonValueKind.Undefined and not JsonValueKind.Null) { var current = response.Data; + + ref var segment = ref MemoryMarshal.GetArrayDataReference(_path); + ref var end = ref Unsafe.Add(ref segment, _path.Length); - for (var i = 0; i < Path.Count; i++) + while (Unsafe.IsAddressLessThan(ref segment, ref end)) { if (current.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) { return current; } - current.TryGetProperty(Path[i], out var propertyValue); + current.TryGetProperty(segment, out var propertyValue); current = propertyValue; + segment = ref Unsafe.Add(ref segment, 1); } return current; @@ -188,75 +171,100 @@ protected JsonElement UnwrapResult(GraphQLResponse response) /// protected override void FormatProperties(Utf8JsonWriter writer) { - writer.WriteString("subgraph", SubgraphName); - writer.WriteString("document", Document); - writer.WriteNumber("selectionSetId", SelectionSet.Id); + writer.WriteString(SubgraphProp, SubgraphName); + writer.WriteString(DocumentProp, DocumentProp); + writer.WriteNumber(SelectionSetIdProp, SelectionSet.Id); - if (Path.Count > 0) + if (_path.Length > 0) { - writer.WritePropertyName("path"); + writer.WritePropertyName(PathProp); writer.WriteStartArray(); + + ref var segment = ref MemoryMarshal.GetArrayDataReference(_path); + ref var end = ref Unsafe.Add(ref segment, _path.Length); - foreach (var path in Path) + while (Unsafe.IsAddressLessThan(ref segment, ref end)) { - writer.WriteStringValue(path); + writer.WriteStringValue(segment); + segment = ref Unsafe.Add(ref segment, 1); } + writer.WriteEndArray(); } - if (Requires.Count > 0) + if (_provides.Length > 0) { - writer.WritePropertyName("requires"); + writer.WritePropertyName(ProvidesProp); writer.WriteStartArray(); + + ref var export = ref MemoryMarshal.GetArrayDataReference(_provides); + ref var end = ref Unsafe.Add(ref export, _provides.Length); - foreach (var requirement in Requires) + while (Unsafe.IsAddressLessThan(ref export, ref end)) { writer.WriteStartObject(); - writer.WriteString("variable", requirement); + writer.WriteString(VariableProp, export); writer.WriteEndObject(); + + export = ref Unsafe.Add(ref export, 1); } + writer.WriteEndArray(); } - if (ForwardedVariables.Count > 0) + if (_requires.Length > 0) { - writer.WritePropertyName("forwardedVariables"); + writer.WritePropertyName(RequiresProp); writer.WriteStartArray(); + + ref var requirement = ref MemoryMarshal.GetArrayDataReference(_requires); + ref var end = ref Unsafe.Add(ref requirement, _requires.Length); - foreach (var variable in ForwardedVariables) + while (Unsafe.IsAddressLessThan(ref requirement, ref end)) { writer.WriteStartObject(); - writer.WriteString("variable", variable); + writer.WriteString(VariableProp, requirement); writer.WriteEndObject(); } + writer.WriteEndArray(); } - } -} -internal sealed class ReformatVariableRewriter : SyntaxRewriter, ISyntaxVisitorContext -{ - private static readonly ReformatVariableRewriter _instance = new(); - - public static IValueNode Rewrite(IValueNode node) - { - if(_instance.Rewrite(node, _instance) is IValueNode rewritten) + if (_forwardedVariables.Length > 0) { - return rewritten; + writer.WritePropertyName(ForwardedVariablesProp); + writer.WriteStartArray(); + + ref var variable = ref MemoryMarshal.GetArrayDataReference(_forwardedVariables); + ref var end = ref Unsafe.Add(ref variable, _forwardedVariables.Length); + + while (Unsafe.IsAddressLessThan(ref variable, ref end)) + { + writer.WriteStartObject(); + writer.WriteString(VariableProp, variable); + writer.WriteEndObject(); + } + writer.WriteEndArray(); } - - return NullValueNode.Default; } - protected override IValueNode? RewriteCustomValue(IValueNode node, ReformatVariableRewriter context) + protected static ValueTask ReturnResult(GraphQLResponse response) { - if(node is FileValueNode fileValueNode) + response.Dispose(); + return default; + } + + protected static ValueTask ReturnResults(GraphQLResponse[] responses) + { + ref var response = ref MemoryMarshal.GetArrayDataReference(responses); + ref var end = ref Unsafe.Add(ref response, responses.Length); + + while (Unsafe.IsAddressLessThan(ref response, ref end)) { - return new FileReferenceNode( - fileValueNode.Value.OpenReadStream, - fileValueNode.Value.Name); + response.Dispose(); + response = ref Unsafe.Add(ref response, 1); } - - return node; + + return default; } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs index 0919990bc8f..bafba400087 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs @@ -1,3 +1,4 @@ +using Internal.Runtime.CompilerServices; using System.Diagnostics; using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; @@ -212,7 +213,8 @@ protected virtual SelectionSetNode CreateSelectionSetNode( while (next) { var possibleType = typeEnumerator.Current; - var selectionSet = (SelectionSet)context.Operation.GetSelectionSet(parentSelection, possibleType); + var selectionSet = Unsafe.As( + context.Operation.GetSelectionSet(parentSelection, possibleType)); var onlyIntrospection = CreateSelectionNodes( @@ -399,9 +401,9 @@ protected void ResolveRequirements( var argumentValue = selection.Arguments[argumentVariable.ArgumentName]; context.VariableValues.Add(variable.Name, argumentValue.ValueLiteral!); TryForwardVariable( - context, - resolver.SubgraphName, - resolver, + context, + resolver.SubgraphName, + resolver, argumentValue, argumentVariable.ArgumentName); } @@ -428,10 +430,10 @@ protected void ResolveRequirements( var argumentValue = parent.Arguments[argumentVariable.ArgumentName]; context.VariableValues.Add(variable.Name, argumentValue.ValueLiteral!); TryForwardVariable( - context, + context, resolver.SubgraphName, - resolver, - argumentValue, + resolver, + argumentValue, argumentVariable.ArgumentName); } } @@ -521,4 +523,4 @@ private class VariableVisitorContext : ISyntaxVisitorContext { public HashSet VariableNodes { get; } = new(SyntaxComparer.BySyntax); } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs b/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs new file mode 100644 index 00000000000..39de375b9f1 --- /dev/null +++ b/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs @@ -0,0 +1,67 @@ +using System.Buffers; + +namespace HotChocolate.Fusion.Planning; + +internal static class CollectionUtils +{ + public static string[] CopyToArray(IReadOnlyList list) + { + if (list.Count == 0) + { + return Array.Empty(); + } + + var array = new string[list.Count]; + + for (var i = 0; i < list.Count; i++) + { + array[i] = list[i]; + } + + return array; + } + + public static string[] CopyToArray(IEnumerable enumerable, ref string[]? buffer, ref int usedBufferCapacity) + { + using var enumerator = enumerable.GetEnumerator(); + var next = enumerator.MoveNext(); + + // if the enumerable holds no elements we will use Array.Empty to + // not allocate empty arrays for every empty enumeration. + if (!next) + { + return Array.Empty(); + } + + // now that we know we have items we will allocate our temp + // list to temporarily store the elements on. + buffer ??= ArrayPool.Shared.Rent(64); + var capacity = buffer.Length; + var index = 0; + + while (next) + { + if (capacity <= buffer.Length) + { + var temp = ArrayPool.Shared.Rent(capacity * 2); + Buffer.BlockCopy(buffer, 0, temp, 0, index); + ArrayPool.Shared.Return(buffer, true); + buffer = temp; + } + + buffer[index++] = enumerator.Current; + next = enumerator.MoveNext(); + } + + // now lets copy the stuff into its array + var array = new string[buffer.Length]; + Buffer.BlockCopy(buffer, 0, array, 0, index); + + if (array.Length > usedBufferCapacity) + { + usedBufferCapacity = array.Length; + } + + return array; + } +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs new file mode 100644 index 00000000000..1b1ef29a183 --- /dev/null +++ b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs @@ -0,0 +1,22 @@ +namespace HotChocolate.Fusion.Planning; + +internal static class Utf8QueryPlanPropertyNames +{ + public static ReadOnlySpan SelectionSetIdsProp => "selectionSetIds"u8; + + public static ReadOnlySpan PathProp => "path"u8; + + public static ReadOnlySpan SubgraphProp => "subgraph"u8; + + public static ReadOnlySpan DocumentProp => "document"u8; + + public static ReadOnlySpan SelectionSetIdProp => "selectionSetId"u8; + + public static ReadOnlySpan RequiresProp => "requires"u8; + + public static ReadOnlySpan ProvidesProp => "provides"u8; + + public static ReadOnlySpan VariableProp => "variable"u8; + + public static ReadOnlySpan ForwardedVariablesProp => "forwardedVariables"u8; +} \ No newline at end of file From cb5c67507f01e746057c0f4bb885f0f90f672bc9 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 00:51:46 +0200 Subject: [PATCH 02/17] edits --- .../src/Core/HotChocolate.Fusion.csproj | 4 ++ .../ExecutionNodeBuilderMiddleware.cs | 16 +++---- .../Fusion/src/Core/Planning/Nodes/Resolve.cs | 26 +++++------ .../Core/Planning/Nodes/ResolverNodeBase.cs | 44 +++++++++---------- .../RequestDocumentFormatter.cs | 2 +- .../Fusion/src/Directory.Build.props | 1 + 6 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj b/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj index 896941fb02c..e7f6eede766 100644 --- a/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj +++ b/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj @@ -5,6 +5,10 @@ HotChocolate.Fusion enable enable + + $(WarningsAsErrors);nullable + + true diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs index 4b036a682e2..dbfe283ed8c 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs @@ -151,7 +151,7 @@ private Resolve CreateResolveNode( private TransportFeatures DetermineTransportFeatures( QueryPlanContext context) { - if (context.ForwardedVariables.Count == 0 || + if (context.ForwardedVariables.Count == 0 || !_schema.TryGetType("Upload", out _)) { return TransportFeatures.Standard; @@ -163,17 +163,17 @@ private TransportFeatures DetermineTransportFeatures( foreach (var variable in context.ForwardedVariables) { var typeName = variable.Type.NamedType().Name.Value; - + if (typeName.EqualsOrdinal("Upload")) { return TransportFeatures.All; } - + if (_schema.TryGetType(typeName, out var inputObjectType)) { processed ??= new HashSet(); next ??= new Stack(); - + processed.Add(inputObjectType); next.Push(inputObjectType); @@ -187,7 +187,7 @@ private TransportFeatures DetermineTransportFeatures( { return TransportFeatures.All; } - + if(fieldType is InputObjectType nextInputObjectType && processed.Add(nextInputObjectType)) { @@ -197,7 +197,7 @@ private TransportFeatures DetermineTransportFeatures( } } } - + processed?.Clear(); return TransportFeatures.Standard; } @@ -213,7 +213,7 @@ private Resolve CreateResolveNodeNode( executionStep.SelectionSetTypeMetadata.Name); context.RegisterSelectionSet(selectionSet); - + var config = new ResolverNodeBase.Config( executionStep.SelectEntityStep.SubgraphName, requestDocument, @@ -259,7 +259,7 @@ private ResolveByKeyBatch CreateResolveByKeyBatchNode( argumentTypes = temp; } - + var config = new ResolverNodeBase.Config( executionStep.SubgraphName, request.Document, diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs index 63f53c33b15..c354ece8894 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs @@ -61,7 +61,7 @@ protected override async Task OnExecuteAsync( // Since we are not fully deserializing the responses we cannot release the memory here // but need to wait until the transport layer is finished and disposes the result. context.Result.RegisterForCleanup(responses, ReturnResults); - + ProcessResponses(context, executionState, requests, responses, SubgraphName); } } @@ -90,27 +90,27 @@ protected override async Task OnExecuteNodesAsync( } private void InitializeRequests( - FusionExecutionContext context, - List executionState, + FusionExecutionContext context, + List executionState, SubgraphGraphQLRequest[] requests) { ref var state = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(executionState)); ref var request = ref MemoryMarshal.GetArrayDataReference(requests); - ref var end = ref Unsafe.Add(ref state, executionState.Count); - + ref var end = ref Unsafe.Add(ref state, executionState.Count); + while (Unsafe.IsAddressLessThan(ref state, ref end)) { TryInitializeExecutionState(context.QueryPlan, state); request = CreateRequest(context.OperationContext.Variables, state.VariableValues); - state = ref Unsafe.Add(ref state, 1); - request = ref Unsafe.Add(ref request, 1); + state = ref Unsafe.Add(ref state, 1)!; + request = ref Unsafe.Add(ref request, 1)!; } } private void ProcessResponses( FusionExecutionContext context, - List executionStates, + List executionStates, SubgraphGraphQLRequest[] requests, GraphQLResponse[] responses, string subgraphName) @@ -136,10 +136,10 @@ private void ProcessResponses( // next we need to extract any variables that we need for followup requests. ExtractVariables(data, context.QueryPlan, selectionSet, exportKeys, variableValues); - - state = ref Unsafe.Add(ref state, 1); - request = ref Unsafe.Add(ref request, 1); - response = ref Unsafe.Add(ref response, 1); + + state = ref Unsafe.Add(ref state, 1)!; + request = ref Unsafe.Add(ref request, 1)!; + response = ref Unsafe.Add(ref response, 1)!; } } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs index 2051376c555..c0a43123bbd 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs @@ -48,11 +48,11 @@ protected ResolverNodeBase(int id, Config config) _transportFeatures = config.TransportFeatures; _hasDependencies = _requires.Length > 0 || _forwardedVariables.Length > 0; } - + protected string SubgraphName => _subgraphName; - + protected internal SelectionSet SelectionSet => _selectionSet; - + protected string[] Requires => _requires; protected string[] Path => _path; @@ -92,7 +92,7 @@ protected SubgraphGraphQLRequest CreateRequest( fields.Add(new ObjectFieldNode(forwardedVariable, value)); } - forwardedVariable = ref Unsafe.Add(ref forwardedVariable, 1); + forwardedVariable = ref Unsafe.Add(ref forwardedVariable, 1)!; } } @@ -111,11 +111,11 @@ protected SubgraphGraphQLRequest CreateRequest( { throw ThrowHelper.Requirement_Is_Missing(requirement, nameof(requirementValues)); } - - requirement = ref Unsafe.Add(ref requirement, 1); + + requirement = ref Unsafe.Add(ref requirement, 1)!; } } - + vars = new ObjectValueNode(fields); } @@ -141,7 +141,7 @@ protected JsonElement UnwrapResult(GraphQLResponse response) if (response.Data.ValueKind is not JsonValueKind.Undefined and not JsonValueKind.Null) { var current = response.Data; - + ref var segment = ref MemoryMarshal.GetArrayDataReference(_path); ref var end = ref Unsafe.Add(ref segment, _path.Length); @@ -154,7 +154,7 @@ protected JsonElement UnwrapResult(GraphQLResponse response) current.TryGetProperty(segment, out var propertyValue); current = propertyValue; - segment = ref Unsafe.Add(ref segment, 1); + segment = ref Unsafe.Add(ref segment, 1)!; } return current; @@ -179,16 +179,16 @@ protected override void FormatProperties(Utf8JsonWriter writer) { writer.WritePropertyName(PathProp); writer.WriteStartArray(); - + ref var segment = ref MemoryMarshal.GetArrayDataReference(_path); ref var end = ref Unsafe.Add(ref segment, _path.Length); while (Unsafe.IsAddressLessThan(ref segment, ref end)) { writer.WriteStringValue(segment); - segment = ref Unsafe.Add(ref segment, 1); + segment = ref Unsafe.Add(ref segment, 1)!; } - + writer.WriteEndArray(); } @@ -196,7 +196,7 @@ protected override void FormatProperties(Utf8JsonWriter writer) { writer.WritePropertyName(ProvidesProp); writer.WriteStartArray(); - + ref var export = ref MemoryMarshal.GetArrayDataReference(_provides); ref var end = ref Unsafe.Add(ref export, _provides.Length); @@ -205,10 +205,10 @@ protected override void FormatProperties(Utf8JsonWriter writer) writer.WriteStartObject(); writer.WriteString(VariableProp, export); writer.WriteEndObject(); - - export = ref Unsafe.Add(ref export, 1); + + export = ref Unsafe.Add(ref export, 1)!; } - + writer.WriteEndArray(); } @@ -216,7 +216,7 @@ protected override void FormatProperties(Utf8JsonWriter writer) { writer.WritePropertyName(RequiresProp); writer.WriteStartArray(); - + ref var requirement = ref MemoryMarshal.GetArrayDataReference(_requires); ref var end = ref Unsafe.Add(ref requirement, _requires.Length); @@ -226,7 +226,7 @@ protected override void FormatProperties(Utf8JsonWriter writer) writer.WriteString(VariableProp, requirement); writer.WriteEndObject(); } - + writer.WriteEndArray(); } @@ -253,7 +253,7 @@ protected static ValueTask ReturnResult(GraphQLResponse response) response.Dispose(); return default; } - + protected static ValueTask ReturnResults(GraphQLResponse[] responses) { ref var response = ref MemoryMarshal.GetArrayDataReference(responses); @@ -262,9 +262,9 @@ protected static ValueTask ReturnResults(GraphQLResponse[] responses) while (Unsafe.IsAddressLessThan(ref response, ref end)) { response.Dispose(); - response = ref Unsafe.Add(ref response, 1); + response = ref Unsafe.Add(ref response, 1)!; } - + return default; } -} \ No newline at end of file +} diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs index bafba400087..3afe7dffefa 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs @@ -322,7 +322,7 @@ protected virtual bool CreateSelectionNodes( } NEXT: - selection = ref Unsafe.Add(ref selection, 1); + selection = ref Unsafe.Add(ref selection, 1)!; } // append exports that were required by other execution steps. diff --git a/src/HotChocolate/Fusion/src/Directory.Build.props b/src/HotChocolate/Fusion/src/Directory.Build.props index a9c57944138..4f91211e2ae 100644 --- a/src/HotChocolate/Fusion/src/Directory.Build.props +++ b/src/HotChocolate/Fusion/src/Directory.Build.props @@ -4,6 +4,7 @@ $(NoWarn);CA1812 + enable From c4bcfd4a09d3df205dd422da28be8ec350a68ce1 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 01:02:24 +0200 Subject: [PATCH 03/17] edits --- .../Utilities/ObjectToDictionaryConverter.cs | 10 ++-- .../ExecutionNodeBuilderMiddleware.cs | 12 +++-- .../ExecutionTreeBuilderMiddleware.cs | 11 +++-- .../Core/Planning/Nodes/ResolveByKeyBatch.cs | 47 ++++++++++--------- .../src/Core/Planning/Nodes/Subscribe.cs | 36 ++------------ .../RequestDocumentFormatter.cs | 1 - 6 files changed, 50 insertions(+), 67 deletions(-) diff --git a/src/HotChocolate/Core/src/Types/Utilities/ObjectToDictionaryConverter.cs b/src/HotChocolate/Core/src/Types/Utilities/ObjectToDictionaryConverter.cs index d055ba7fbfb..3b56d356e6a 100644 --- a/src/HotChocolate/Core/src/Types/Utilities/ObjectToDictionaryConverter.cs +++ b/src/HotChocolate/Core/src/Types/Utilities/ObjectToDictionaryConverter.cs @@ -3,16 +3,20 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Dynamic; using System.Reflection; namespace HotChocolate.Utilities; -internal class ObjectToDictionaryConverter(ITypeConverter converter) +internal class ObjectToDictionaryConverter { - private readonly ITypeConverter _converter = converter ?? throw new ArgumentNullException(nameof(converter)); + private readonly ITypeConverter _converter; private readonly ConcurrentDictionary _properties = new(); + public ObjectToDictionaryConverter(ITypeConverter converter) + { + _converter = converter ?? throw new ArgumentNullException(nameof(converter)); + } + public object Convert(object obj) { if(obj is null) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs index dbfe283ed8c..967b5ebad78 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs @@ -285,16 +285,18 @@ private Subscribe CreateSubscribeNode( OperationType.Subscription); context.RegisterSelectionSet(selectionSet); - - return new Subscribe( - context.NextNodeId(), + + var config = new ResolverNodeBase.Config( executionStep.SubgraphName, request.Document, selectionSet, - executionStep.Variables.Values.ToArray(), + context.Exports.GetExportKeys(executionStep), + executionStep.Variables.Values, + context.ForwardedVariables.Select(t => t.Variable.Name.Value), request.Path, - context.ForwardedVariables.Select(t => t.Variable.Name.Value).ToArray(), DetermineTransportFeatures(context)); + + return new Subscribe(context.NextNodeId(), config); } private ISelectionSet ResolveSelectionSet( diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs index 564ff91367b..8d581b0bd8f 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs @@ -1,3 +1,4 @@ +using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Language; using HotChocolate.Utilities; @@ -56,7 +57,7 @@ private void ProcessBacklog( var single = next.Batch[0]; next.Parent.AddNode(single.Node); - var selectionSet = ResolveSelectionSet(context, single.Step); + var selectionSet = Unsafe.As(ResolveSelectionSet(context, single.Step)); if (NeedsComposition(single.Step, selectionSet)) { @@ -72,11 +73,11 @@ private void ProcessBacklog( else { var parallel = new Parallel(context.NextNodeId()); - var selectionSets = new List(); + var selectionSets = new List(); foreach (var item in next.Batch) { - var selectionSet = ResolveSelectionSet(context, item.Step); + var selectionSet = Unsafe.As(ResolveSelectionSet(context, item.Step)); if (NeedsComposition(item.Step, selectionSet)) { @@ -106,7 +107,7 @@ private void ProcessBacklog( } } - bool NeedsComposition(ExecutionStep step, ISelectionSet selectionSet) + bool NeedsComposition(ExecutionStep step, SelectionSet selectionSet) { var steps = lookup[selectionSet]; steps.Remove(step); @@ -193,7 +194,7 @@ private QueryPlanNode CreateSubscriptionRoot( var parent = new Sequence(context.NextNodeId()); root.AddNode(parent); - var selectionSet = ResolveSelectionSet(context, step); + var selectionSet = Unsafe.As(ResolveSelectionSet(context, step)); var compose = new Compose(context.NextNodeId(), selectionSet); parent.AddNode(compose); context.Complete(step); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs index a1a278f4723..258a6e60e8c 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs @@ -1,9 +1,7 @@ -using System.Collections.Frozen; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Text.Json; -using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; using HotChocolate.Fusion.Execution; using HotChocolate.Language; @@ -35,7 +33,7 @@ protected override async Task OnExecuteAsync( var batchExecutionState = CreateBatchBatchState(executionState, Requires); // Create the batch subgraph request. - var variableValues = BuildVariables(batchExecutionState); + var variableValues = BuildVariables(batchExecutionState, _argumentTypes); var request = CreateRequest(context.OperationContext.Variables, variableValues); // Once we have the batch request, we will enqueue it for execution with @@ -152,7 +150,7 @@ private Dictionary UnwrapResult( GraphQLResponse response, IReadOnlyList exportKeys) { - var data = response.Data; + JsonElement data = response.Data; var path = Path; if (data.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) @@ -162,7 +160,7 @@ private Dictionary UnwrapResult( if (path.Length > 0) { - data = LiftData(); + data = LiftData(data, Path); } if (data.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) @@ -202,31 +200,36 @@ private Dictionary UnwrapResult( } return result; + } + + private static JsonElement LiftData(JsonElement data, string[] path) + { + if (data.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) + { + return data; + } + + var current = data; + + ref var segment = ref MemoryMarshal.GetArrayDataReference(path); + ref var end = ref Unsafe.Add(ref segment, path.Length); - JsonElement LiftData() + while(Unsafe.IsAddressLessThan(ref segment, ref end)) { - if (data.ValueKind is not JsonValueKind.Undefined and not JsonValueKind.Null) + if (current.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) { - var current = data; - - for (var i = 0; i < _path.Count; i++) - { - if (current.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null) - { - return current; - } - - current.TryGetProperty(_path[i], out var propertyValue); - current = propertyValue; - } - return current; } - return data; + current.TryGetProperty(segment, out var propertyValue); + current = propertyValue; + + segment = ref Unsafe.Add(ref segment, 1)!; } - } + return current; + } + private static BatchExecutionState[] CreateBatchBatchState(List executionState, string[] requires) { var batchExecutionState = new BatchExecutionState[executionState.Count]; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs index 64ea9d9dffe..5bce27cb89d 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs @@ -24,37 +24,11 @@ internal sealed class Subscribe : ResolverNodeBase /// /// The unique id of this node. /// - /// - /// The name of the subgraph on which this request handler executes. + /// + /// Gets the resolver configuration. /// - /// - /// The GraphQL request document. - /// - /// - /// The selection set for which this request provides a patch. - /// - /// - /// The variables that this request handler requires to create a request. - /// - /// - /// The path to the data that this request handler needs to extract. - /// - /// - /// The variables that this request handler forwards to the subgraph. - /// - /// - /// The transport features that are required by this node. - /// - public Subscribe( - int id, - string subgraphName, - DocumentNode document, - ISelectionSet selectionSet, - IReadOnlyList requires, - IReadOnlyList path, - IReadOnlyList forwardedVariables, - TransportFeatures transportFeatures) - : base(id, subgraphName, document, selectionSet, requires, path, forwardedVariables, transportFeatures) + public Subscribe(int id, Config config) + : base(id, config) { } @@ -160,7 +134,7 @@ internal async IAsyncEnumerable SubscribeAsync( } } -static file class SubscriptionNodeExtensions +file static class SubscriptionNodeExtensions { public static FusionExecutionContext Clone(this FusionExecutionContext context) { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs index 3afe7dffefa..9956498b63b 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs @@ -1,4 +1,3 @@ -using Internal.Runtime.CompilerServices; using System.Diagnostics; using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; From ab9d3fd3f0a189aa8ef0d944a1cab19b2a16e170 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 10:32:46 +0200 Subject: [PATCH 04/17] edits --- .../Core/Planning/Nodes/ResolveByKeyBatch.cs | 26 +++--- .../Core/Planning/Nodes/ResolverNodeBase.cs | 8 +- .../NodeRequestDocumentFormatter.cs | 2 +- .../src/Core/ServiceConfigurationException.cs | 6 ++ .../src/Core/Utilities/CollectionUtils.cs | 11 +-- ...eviews_And_Products_Query_TopProducts.snap | 7 +- ...d_Reviews_And_Products_Query_TypeName.snap | 7 +- ...ts.Authors_And_Reviews_Batch_Requests.snap | 18 +++-- ...hors_And_Reviews_Query_GetUserReviews.snap | 18 +++-- ...Authors_And_Reviews_Query_ReviewsUser.snap | 18 +++-- ...egrationTests.Require_Data_In_Context.snap | 75 ++++++++--------- ...rationTests.Require_Data_In_Context_2.snap | 71 ++++++++-------- ...rationTests.Require_Data_In_Context_3.snap | 81 ++++++++++--------- ...Tests.Accounts_Offline_Author_NonNull.snap | 18 +++-- ...ests.Accounts_Offline_Author_Nullable.snap | 18 +++-- ..._Offline_Reviews_ListElement_Nullable.snap | 18 +++-- ...ts.Query_Interface_List_With_Fragment.snap | 18 +++-- ...ry_Interface_List_With_Fragment_Fetch.snap | 18 +++-- .../RequestPlannerTests.Query_Plan_01.snap | 18 +++-- ...estPlannerTests.Query_Plan_02_Aliases.snap | 32 +++++--- ...nerTests.Query_Plan_05_TypeName_Field.snap | 7 +- ...ry_Plan_10_Two_Mutation_Same_SubGraph.snap | 10 ++- ...ery_Plan_11_Two_Mutation_Two_SubGraph.snap | 10 ++- ...nerTests.Query_Plan_13_Subscription_2.snap | 5 ++ ...stPlannerTests.Query_Plan_19_Requires.snap | 38 ++++++--- ...tPlannerTests.Query_Plan_20_DeepQuery.snap | 46 ++++++----- ...n_21_Field_Requirement_Not_In_Context.snap | 38 ++++++--- ...rTests.Query_Plan_23_Interfaces_Merge.snap | 18 +++-- ...eld_Requirement_And_Fields_In_Context.snap | 38 ++++++--- ..._Plan_25_Variables_Are_Passed_Through.snap | 7 +- 30 files changed, 423 insertions(+), 282 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs index 258a6e60e8c..fe438d584cf 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs @@ -67,6 +67,7 @@ private static void InitializeRequests(FusionExecutionContext context, List BuildVariables( } var variableValues = new Dictionary(); - var uniqueWorkItems = new List(); + var uniqueState = new List(); var processed = new HashSet(); - foreach (var workItem in batchExecutionState) + ref var batchState = ref MemoryMarshal.GetArrayDataReference(batchExecutionState); + ref var end = ref Unsafe.Add(ref batchState, batchExecutionState.Length); + + while (Unsafe.IsAddressLessThan(ref batchState, ref end)) { - if (processed.Add(workItem.Key)) + if (processed.Add(batchState.Key)) { - uniqueWorkItems.Add(workItem); + uniqueState.Add(batchState); } + + batchState = ref Unsafe.Add(ref batchState, 1); } foreach (var key in batchExecutionState[0].VariableValues.Keys) @@ -124,7 +130,7 @@ private static Dictionary BuildVariables( { var list = new List(); - foreach (var value in uniqueWorkItems) + foreach (var value in uniqueState) { if (value.VariableValues.TryGetValue(key, out var variableValue)) { @@ -245,8 +251,8 @@ private static BatchExecutionState[] CreateBatchBatchState(List var key = FormatKeyValue(state.VariableValues[requires[0]]); batchState = new BatchExecutionState(key, state); - state = ref Unsafe.Add(ref state, 1); - batchState = ref Unsafe.Add(ref batchState, 1); + state = ref Unsafe.Add(ref state, 1)!; + batchState = ref Unsafe.Add(ref batchState, 1)!; } } else @@ -261,13 +267,13 @@ private static BatchExecutionState[] CreateBatchBatchState(List while (Unsafe.IsAddressLessThan(ref key, ref keyEnd)) { keyBuilder.Append(FormatKeyValue(state.VariableValues[key])); - key = ref Unsafe.Add(ref key, 1); + key = ref Unsafe.Add(ref key, 1)!; } batchState = new BatchExecutionState(key, state); - state = ref Unsafe.Add(ref state, 1); - batchState = ref Unsafe.Add(ref batchState, 1); + state = ref Unsafe.Add(ref state, 1)!; + batchState = ref Unsafe.Add(ref batchState, 1)!; } } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs index c0a43123bbd..cfe9a9fb3b0 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs @@ -171,8 +171,8 @@ protected JsonElement UnwrapResult(GraphQLResponse response) /// protected override void FormatProperties(Utf8JsonWriter writer) { - writer.WriteString(SubgraphProp, SubgraphName); - writer.WriteString(DocumentProp, DocumentProp); + writer.WriteString(SubgraphProp, _subgraphName); + writer.WriteString(DocumentProp, _document); writer.WriteNumber(SelectionSetIdProp, SelectionSet.Id); if (_path.Length > 0) @@ -225,6 +225,8 @@ protected override void FormatProperties(Utf8JsonWriter writer) writer.WriteStartObject(); writer.WriteString(VariableProp, requirement); writer.WriteEndObject(); + + requirement = ref Unsafe.Add(ref requirement, 1)!; } writer.WriteEndArray(); @@ -243,6 +245,8 @@ protected override void FormatProperties(Utf8JsonWriter writer) writer.WriteStartObject(); writer.WriteString(VariableProp, variable); writer.WriteEndObject(); + + variable = ref Unsafe.Add(ref variable, 1)!; } writer.WriteEndArray(); } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs index 0f506002133..6f169e72625 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs @@ -213,7 +213,7 @@ protected override bool CreateSelectionNodes( } NEXT: - selection = ref Unsafe.Add(ref selection, 1); + selection = ref Unsafe.Add(ref selection, 1)!; } if (selectionSet.Selections.Count == 0 && selectionNodes.Count == 0) diff --git a/src/HotChocolate/Fusion/src/Core/ServiceConfigurationException.cs b/src/HotChocolate/Fusion/src/Core/ServiceConfigurationException.cs index dd1da444a53..e1151512e53 100644 --- a/src/HotChocolate/Fusion/src/Core/ServiceConfigurationException.cs +++ b/src/HotChocolate/Fusion/src/Core/ServiceConfigurationException.cs @@ -15,6 +15,12 @@ public ServiceConfigurationException( Exception inner) : base(message, inner) { } +#if NET8_0_OR_GREATER + [Obsolete( + "This API supports obsolete formatter-based serialization. " + + "It should not be called or extended by application code.", + true)] +#endif protected ServiceConfigurationException( SerializationInfo info, StreamingContext context) diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs b/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs index 39de375b9f1..747513c527a 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs @@ -41,12 +41,13 @@ public static string[] CopyToArray(IEnumerable enumerable, ref string[]? while (next) { - if (capacity <= buffer.Length) + if (capacity <= index) { var temp = ArrayPool.Shared.Rent(capacity * 2); - Buffer.BlockCopy(buffer, 0, temp, 0, index); + buffer.AsSpan(0, index).CopyTo(temp); ArrayPool.Shared.Return(buffer, true); buffer = temp; + capacity = buffer.Length; } buffer[index++] = enumerator.Current; @@ -54,14 +55,14 @@ public static string[] CopyToArray(IEnumerable enumerable, ref string[]? } // now lets copy the stuff into its array - var array = new string[buffer.Length]; - Buffer.BlockCopy(buffer, 0, array, 0, index); + var array = new string[index]; + buffer.AsSpan(0, index).CopyTo(array); if (array.Length > usedBufferCapacity) { usedBufferCapacity = array.Length; } - + return array; } } \ No newline at end of file diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap index 320f6b21ace..15bd18aad9c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap @@ -25,7 +25,12 @@ QueryPlan "type": "Resolve", "subgraph": "Products", "document": "query TopProducts_1 { topProducts(first: 2) { name __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap index a0447d17eef..c485ba1c9f2 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap @@ -33,7 +33,12 @@ QueryPlan "type": "Resolve", "subgraph": "Products", "document": "query TopProducts_1 { topProducts(first: 2) { __typename __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] } ] }, diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap index 3492e4582a3..2edac77cc56 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap @@ -22,7 +22,12 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews2", "document": "query GetUser_1 { reviews { body author { __fusion_exports__1: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -35,15 +40,14 @@ QueryPlan "subgraph": "Accounts", "document": "query GetUser_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { birthdate __fusion_exports__1: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap index dd3b23ae62d..270a525c5bd 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap @@ -25,7 +25,12 @@ QueryPlan "type": "Resolve", "subgraph": "Accounts", "document": "query GetUser_1 { users { name __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -38,15 +43,14 @@ QueryPlan "subgraph": "Reviews2", "document": "query GetUser_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { reviews { body author { name } } __fusion_exports__1: id } } }", "selectionSetId": 1, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap index 10a9fd99d07..5d7929c3b82 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap @@ -46,7 +46,12 @@ QueryPlan "type": "Resolve", "subgraph": "Accounts", "document": "query GetUser_2 { users { name __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] } ] }, @@ -61,15 +66,14 @@ QueryPlan "subgraph": "Reviews2", "document": "query GetUser_3($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { reviews { body author { name } } __fusion_exports__1: id } } }", "selectionSetId": 1, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap index f8191a4a32a..76b257c3daa 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap @@ -30,7 +30,15 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews2", "document": "query Requires_1 { reviews { body author { name __fusion_exports__3: id } product { __fusion_exports__4: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__3" + }, + { + "variable": "__fusion_exports__4" + } + ] }, { "type": "Compose", @@ -46,15 +54,14 @@ QueryPlan "subgraph": "Accounts", "document": "query Requires_2($__fusion_exports__3: [ID!]!) { nodes(ids: $__fusion_exports__3) { ... on User { birthdate __fusion_exports__3: id } } }", "selectionSetId": 4, - "argumentTypes": [ - { - "argument": "__fusion_exports__3", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__3" + } + ], "requires": [ { "variable": "__fusion_exports__3" @@ -66,15 +73,20 @@ QueryPlan "subgraph": "Products", "document": "query Requires_4($__fusion_exports__4: [ID!]!) { nodes(ids: $__fusion_exports__4) { ... on Product { name __fusion_exports__1: dimension { size } __fusion_exports__2: dimension { weight } __fusion_exports__4: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__4", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + }, + { + "variable": "__fusion_exports__4" + } + ], "requires": [ { "variable": "__fusion_exports__4" @@ -123,6 +135,11 @@ QueryPlan Result --------------- { + "errors": [ + { + "message": "Unexpected Execution Error" + } + ], "data": { "reviews": [ { @@ -131,13 +148,7 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": { - "name": "Table", - "deliveryEstimate": { - "min": 400, - "max": 800 - } - } + "product": {} }, { "body": "Too expensive.", @@ -145,13 +156,7 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": { - "name": "Couch", - "deliveryEstimate": { - "min": 2650, - "max": 5300 - } - } + "product": {} }, { "body": "Could be better.", @@ -159,13 +164,7 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": { - "name": "Chair", - "deliveryEstimate": { - "min": 45, - "max": 90 - } - } + "product": {} }, { "body": "Prefer something else.", @@ -173,13 +172,7 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": { - "name": "Table", - "deliveryEstimate": { - "min": 400, - "max": 800 - } - } + "product": {} } ] } diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap index be0f27f0006..1a455622fb9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap @@ -29,7 +29,15 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews2", "document": "query Requires_1 { reviews { body author { name __fusion_exports__3: id } product { __fusion_exports__4: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__3" + }, + { + "variable": "__fusion_exports__4" + } + ] }, { "type": "Compose", @@ -45,15 +53,14 @@ QueryPlan "subgraph": "Accounts", "document": "query Requires_2($__fusion_exports__3: [ID!]!) { nodes(ids: $__fusion_exports__3) { ... on User { birthdate __fusion_exports__3: id } } }", "selectionSetId": 4, - "argumentTypes": [ - { - "argument": "__fusion_exports__3", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__3" + } + ], "requires": [ { "variable": "__fusion_exports__3" @@ -65,15 +72,20 @@ QueryPlan "subgraph": "Products", "document": "query Requires_4($__fusion_exports__4: [ID!]!) { nodes(ids: $__fusion_exports__4) { ... on Product { __fusion_exports__1: dimension { size } __fusion_exports__2: dimension { weight } __fusion_exports__4: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__4", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + }, + { + "variable": "__fusion_exports__4" + } + ], "requires": [ { "variable": "__fusion_exports__4" @@ -122,6 +134,11 @@ QueryPlan Result --------------- { + "errors": [ + { + "message": "Unexpected Execution Error" + } + ], "data": { "reviews": [ { @@ -130,12 +147,7 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": { - "deliveryEstimate": { - "min": 400, - "max": 800 - } - } + "product": {} }, { "body": "Too expensive.", @@ -143,12 +155,7 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": { - "deliveryEstimate": { - "min": 2650, - "max": 5300 - } - } + "product": {} }, { "body": "Could be better.", @@ -156,12 +163,7 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": { - "deliveryEstimate": { - "min": 45, - "max": 90 - } - } + "product": {} }, { "body": "Prefer something else.", @@ -169,12 +171,7 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": { - "deliveryEstimate": { - "min": 400, - "max": 800 - } - } + "product": {} } ] } diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap index 33af58370f7..b515e670e06 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap @@ -35,7 +35,12 @@ QueryPlan "type": "Resolve", "subgraph": "Accounts", "document": "query Large_1 { users { id name birthdate __fusion_exports__3: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__3" + } + ] }, { "type": "Compose", @@ -48,15 +53,20 @@ QueryPlan "subgraph": "Reviews2", "document": "query Large_2($__fusion_exports__3: [ID!]!) { nodes(ids: $__fusion_exports__3) { ... on User { reviews { body author { name __fusion_exports__4: id } product { id __fusion_exports__5: id } } __fusion_exports__3: id } } }", "selectionSetId": 1, - "argumentTypes": [ - { - "argument": "__fusion_exports__3", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__3" + }, + { + "variable": "__fusion_exports__4" + }, + { + "variable": "__fusion_exports__5" + } + ], "requires": [ { "variable": "__fusion_exports__3" @@ -77,15 +87,14 @@ QueryPlan "subgraph": "Accounts", "document": "query Large_3($__fusion_exports__4: [ID!]!) { nodes(ids: $__fusion_exports__4) { ... on User { birthdate __fusion_exports__4: id } } }", "selectionSetId": 5, - "argumentTypes": [ - { - "argument": "__fusion_exports__4", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__4" + } + ], "requires": [ { "variable": "__fusion_exports__4" @@ -97,15 +106,20 @@ QueryPlan "subgraph": "Products", "document": "query Large_5($__fusion_exports__5: [ID!]!) { nodes(ids: $__fusion_exports__5) { ... on Product { name __fusion_exports__1: dimension { size } __fusion_exports__2: dimension { weight } __fusion_exports__5: id } } }", "selectionSetId": 3, - "argumentTypes": [ - { - "argument": "__fusion_exports__5", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + }, + { + "variable": "__fusion_exports__5" + } + ], "requires": [ { "variable": "__fusion_exports__5" @@ -154,6 +168,11 @@ QueryPlan Result --------------- { + "errors": [ + { + "message": "Unexpected Execution Error" + } + ], "data": { "users": [ { @@ -168,11 +187,7 @@ Result "birthdate": "1815-12-10" }, "product": { - "id": "UHJvZHVjdAppMQ==", - "name": "Table", - "deliveryEstimate": { - "max": 800 - } + "id": "UHJvZHVjdAppMQ==" } }, { @@ -182,11 +197,7 @@ Result "birthdate": "1815-12-10" }, "product": { - "id": "UHJvZHVjdAppMw==", - "name": "Chair", - "deliveryEstimate": { - "max": 90 - } + "id": "UHJvZHVjdAppMw==" } } ] @@ -203,11 +214,7 @@ Result "birthdate": "1912-06-23" }, "product": { - "id": "UHJvZHVjdAppMg==", - "name": "Couch", - "deliveryEstimate": { - "max": 5300 - } + "id": "UHJvZHVjdAppMg==" } }, { @@ -217,11 +224,7 @@ Result "birthdate": "1912-06-23" }, "product": { - "id": "UHJvZHVjdAppMQ==", - "name": "Table", - "deliveryEstimate": { - "max": 800 - } + "id": "UHJvZHVjdAppMQ==" } } ] diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap index a56899423ca..9e8a450d42f 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap @@ -22,7 +22,12 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews", "document": "query ReformatIds_1 { reviews { body author! { __fusion_exports__1: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -35,15 +40,14 @@ QueryPlan "subgraph": "Accounts", "document": "query ReformatIds_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { birthdate __fusion_exports__1: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap index 5a780d5607b..efe546e4e0f 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap @@ -22,7 +22,12 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews", "document": "query ReformatIds_1 { reviews { body author? { __fusion_exports__1: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -35,15 +40,14 @@ QueryPlan "subgraph": "Accounts", "document": "query ReformatIds_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { birthdate __fusion_exports__1: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap index 9dd93b6aa5c..0e0fafc42bc 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap @@ -22,7 +22,12 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews", "document": "query ReformatIds_1 { reviews { body author { __fusion_exports__1: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -35,15 +40,14 @@ QueryPlan "subgraph": "Accounts", "document": "query ReformatIds_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { birthdate __fusion_exports__1: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap index 3d33ddba496..6a705ba38c0 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap @@ -26,7 +26,12 @@ QueryPlan "type": "Resolve", "subgraph": "Appointment", "document": "query Appointments_1 { appointments(after: null, before: null, first: null, last: null) { nodes { patient { __typename ... on Patient1 { id __fusion_exports__1: id } ... on Patient2 { id } } } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -39,15 +44,14 @@ QueryPlan "subgraph": "Patient1", "document": "query Appointments_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on Patient1 { name __fusion_exports__1: id } } }", "selectionSetId": 3, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap index 3d33ddba496..6a705ba38c0 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap @@ -26,7 +26,12 @@ QueryPlan "type": "Resolve", "subgraph": "Appointment", "document": "query Appointments_1 { appointments(after: null, before: null, first: null, last: null) { nodes { patient { __typename ... on Patient1 { id __fusion_exports__1: id } ... on Patient2 { id } } } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -39,15 +44,14 @@ QueryPlan "subgraph": "Patient1", "document": "query Appointments_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on Patient1 { name __fusion_exports__1: id } } }", "selectionSetId": 3, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap index 290587acbb0..ddc824bb3d3 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap @@ -25,7 +25,12 @@ QueryPlan "type": "Resolve", "subgraph": "Accounts", "document": "query GetUser_1 { users { name __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -38,15 +43,14 @@ QueryPlan "subgraph": "Reviews", "document": "query GetUser_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { reviews { body author { name } } __fusion_exports__1: id } } }", "selectionSetId": 1, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap index 1ece7d20f5d..43dfac45714 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap @@ -34,7 +34,15 @@ QueryPlan "type": "Resolve", "subgraph": "Accounts", "document": "query GetUser_1 { a: users { name __fusion_exports__1: id } b: users { name __fusion_exports__2: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + } + ] }, { "type": "Compose", @@ -50,15 +58,14 @@ QueryPlan "subgraph": "Reviews", "document": "query GetUser_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { reviews { body author { name } } __fusion_exports__1: id } } }", "selectionSetId": 4, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" @@ -70,15 +77,14 @@ QueryPlan "subgraph": "Reviews", "document": "query GetUser_3($__fusion_exports__2: [ID!]!) { nodes(ids: $__fusion_exports__2) { ... on User { reviews { body author { name } } __fusion_exports__2: id } } }", "selectionSetId": 1, - "argumentTypes": [ - { - "argument": "__fusion_exports__2", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__2" + } + ], "requires": [ { "variable": "__fusion_exports__2" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap index d264a8a5d73..9427ea8bf88 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap @@ -33,7 +33,12 @@ QueryPlan "type": "Resolve", "subgraph": "Products", "document": "query TopProducts_1 { topProducts(first: 2) { __typename __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] } ] }, diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap index 83f6452cc33..38c9eca4844 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap @@ -33,7 +33,15 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews", "document": "mutation AddReviews_1 { a: addReview(input: { body: \u0022foo\u0022, authorId: 1, upc: 1 }) { review { body author { __fusion_exports__1: id } } } b: addReview(input: { body: \u0022foo\u0022, authorId: 1, upc: 1 }) { review { body author { id __fusion_exports__2: id } } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + } + ] }, { "type": "Compose", diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap index f9d25adb2a5..f0de2624345 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap @@ -33,7 +33,15 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews", "document": "mutation AddReviewAndUser_1 { addReview(input: { body: \u0022foo\u0022, authorId: 1, upc: 1 }) { review { body author { id __fusion_exports__1: id } } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + } + ] }, { "type": "Resolve", diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap index fc84cd55392..136b4ed8549 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap @@ -21,6 +21,11 @@ QueryPlan "subgraph": "Reviews", "document": "subscription OnNewReview_1 { onNewReview { body author { name __fusion_exports__1: id } } }", "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "nodes": [ { "type": "Sequence", diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap index 24382dd574f..994f4a3397e 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap @@ -30,7 +30,15 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews2", "document": "query Requires_1 { reviews { body author { name __fusion_exports__3: id } product { __fusion_exports__4: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__3" + }, + { + "variable": "__fusion_exports__4" + } + ] }, { "type": "Compose", @@ -46,15 +54,14 @@ QueryPlan "subgraph": "Accounts", "document": "query Requires_2($__fusion_exports__3: [ID!]!) { nodes(ids: $__fusion_exports__3) { ... on User { birthdate __fusion_exports__3: id } } }", "selectionSetId": 4, - "argumentTypes": [ - { - "argument": "__fusion_exports__3", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__3" + } + ], "requires": [ { "variable": "__fusion_exports__3" @@ -66,15 +73,20 @@ QueryPlan "subgraph": "Products", "document": "query Requires_4($__fusion_exports__4: [ID!]!) { nodes(ids: $__fusion_exports__4) { ... on Product { name __fusion_exports__1: dimension { size } __fusion_exports__2: dimension { weight } __fusion_exports__4: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__4", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + }, + { + "variable": "__fusion_exports__4" + } + ], "requires": [ { "variable": "__fusion_exports__4" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap index 2bde0638204..53a5737abb8 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap @@ -33,7 +33,12 @@ QueryPlan "type": "Resolve", "subgraph": "Accounts", "document": "query GetUser_1 { users { name __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -46,15 +51,20 @@ QueryPlan "subgraph": "Reviews", "document": "query GetUser_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on User { reviews { body author { name reviews { body author { name __fusion_exports__2: id } } __fusion_exports__3: id } } __fusion_exports__1: id } } }", "selectionSetId": 1, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + }, + { + "variable": "__fusion_exports__3" + } + ], "requires": [ { "variable": "__fusion_exports__1" @@ -75,15 +85,14 @@ QueryPlan "subgraph": "Accounts", "document": "query GetUser_3($__fusion_exports__2: [ID!]!) { nodes(ids: $__fusion_exports__2) { ... on User { birthdate __fusion_exports__2: id } } }", "selectionSetId": 5, - "argumentTypes": [ - { - "argument": "__fusion_exports__2", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__2" + } + ], "requires": [ { "variable": "__fusion_exports__2" @@ -95,15 +104,14 @@ QueryPlan "subgraph": "Accounts", "document": "query GetUser_4($__fusion_exports__3: [ID!]!) { nodes(ids: $__fusion_exports__3) { ... on User { birthdate __fusion_exports__3: id } } }", "selectionSetId": 3, - "argumentTypes": [ - { - "argument": "__fusion_exports__3", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__3" + } + ], "requires": [ { "variable": "__fusion_exports__3" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap index 2ea38c08dea..1db0f756afb 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap @@ -29,7 +29,15 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews2", "document": "query Requires_1 { reviews { body author { name __fusion_exports__3: id } product { __fusion_exports__4: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__3" + }, + { + "variable": "__fusion_exports__4" + } + ] }, { "type": "Compose", @@ -45,15 +53,14 @@ QueryPlan "subgraph": "Accounts", "document": "query Requires_2($__fusion_exports__3: [ID!]!) { nodes(ids: $__fusion_exports__3) { ... on User { birthdate __fusion_exports__3: id } } }", "selectionSetId": 4, - "argumentTypes": [ - { - "argument": "__fusion_exports__3", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__3" + } + ], "requires": [ { "variable": "__fusion_exports__3" @@ -65,15 +72,20 @@ QueryPlan "subgraph": "Products", "document": "query Requires_4($__fusion_exports__4: [ID!]!) { nodes(ids: $__fusion_exports__4) { ... on Product { __fusion_exports__1: dimension { size } __fusion_exports__2: dimension { weight } __fusion_exports__4: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__4", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + }, + { + "variable": "__fusion_exports__4" + } + ], "requires": [ { "variable": "__fusion_exports__4" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap index 51cb6504fb4..895378bcc6d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap @@ -26,7 +26,12 @@ QueryPlan "type": "Resolve", "subgraph": "Appointment", "document": "query Appointments_1 { appointments(after: null, before: null, first: null, last: null) { nodes { patient { __typename ... on Patient1 { id __fusion_exports__1: id } ... on Patient2 { id } } } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", @@ -39,15 +44,14 @@ QueryPlan "subgraph": "Patient1", "document": "query Appointments_2($__fusion_exports__1: [ID!]!) { nodes(ids: $__fusion_exports__1) { ... on Patient1 { name __fusion_exports__1: id } } }", "selectionSetId": 3, - "argumentTypes": [ - { - "argument": "__fusion_exports__1", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + } + ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap index 07133d81bc7..1c09e560443 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap @@ -31,7 +31,15 @@ QueryPlan "type": "Resolve", "subgraph": "Reviews2", "document": "query Requires_1 { reviews { body author { name __fusion_exports__3: id } product { id __fusion_exports__4: id } } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__3" + }, + { + "variable": "__fusion_exports__4" + } + ] }, { "type": "Compose", @@ -47,15 +55,14 @@ QueryPlan "subgraph": "Accounts", "document": "query Requires_2($__fusion_exports__3: [ID!]!) { nodes(ids: $__fusion_exports__3) { ... on User { birthdate __fusion_exports__3: id } } }", "selectionSetId": 4, - "argumentTypes": [ - { - "argument": "__fusion_exports__3", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__3" + } + ], "requires": [ { "variable": "__fusion_exports__3" @@ -67,15 +74,20 @@ QueryPlan "subgraph": "Products", "document": "query Requires_4($__fusion_exports__4: [ID!]!) { nodes(ids: $__fusion_exports__4) { ... on Product { name __fusion_exports__1: dimension { size } __fusion_exports__2: dimension { weight } __fusion_exports__4: id } } }", "selectionSetId": 2, - "argumentTypes": [ - { - "argument": "__fusion_exports__4", - "type": "[ID!]!" - } - ], "path": [ "nodes" ], + "provides": [ + { + "variable": "__fusion_exports__1" + }, + { + "variable": "__fusion_exports__2" + }, + { + "variable": "__fusion_exports__4" + } + ], "requires": [ { "variable": "__fusion_exports__4" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap index 091ed2df489..440249f8924 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap @@ -24,7 +24,12 @@ QueryPlan "type": "Resolve", "subgraph": "Patient1", "document": "query Appointments_1 { patientById(patientId: 1) { name __fusion_exports__1: id } }", - "selectionSetId": 0 + "selectionSetId": 0, + "provides": [ + { + "variable": "__fusion_exports__1" + } + ] }, { "type": "Compose", From 83eedf6bdfc51907f5ca55f37513dabbd2a29fda Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 11:36:30 +0200 Subject: [PATCH 05/17] edits --- .../src/Core/Execution/ExecutionState.cs | 14 ++-- .../src/Core/Execution/ExecutorUtils.cs | 2 +- .../Core/Execution/FusionContextExtensions.cs | 4 +- .../Fusion/src/Core/Execution/RequestState.cs | 10 +-- .../ExecutionNodeBuilderMiddleware.cs | 3 +- .../Fusion/src/Core/Planning/Nodes/Compose.cs | 77 +++++++++++++++++-- .../src/Core/Planning/Nodes/Introspect.cs | 9 +-- .../src/Core/Planning/Nodes/Parallel.cs | 7 ++ .../src/Core/Planning/Nodes/QueryPlan.cs | 10 ++- .../Fusion/src/Core/Planning/Nodes/Resolve.cs | 2 +- .../Core/Planning/Nodes/ResolveByKeyBatch.cs | 23 +++--- .../src/Core/Planning/Nodes/Sequence.cs | 14 ++++ .../src/Core/Planning/Nodes/Subscribe.cs | 4 +- .../Utilities/Utf8QueryPlanPropertyNames.cs | 4 + ...egrationTests.Require_Data_In_Context.snap | 37 ++++++--- ...rationTests.Require_Data_In_Context_2.snap | 33 +++++--- ...rationTests.Require_Data_In_Context_3.snap | 29 ++++--- 17 files changed, 213 insertions(+), 69 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs b/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs index 46173b46c1e..66d0bda9550 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/ExecutionState.cs @@ -10,14 +10,14 @@ namespace HotChocolate.Fusion.Execution; internal sealed class ExecutionState { public ExecutionState( - ISelectionSet selectionSet, + SelectionSet selectionSet, ObjectResult selectionSetResult, - IReadOnlyList exportKeys) + IReadOnlyList provides) { SelectionSet = selectionSet; SelectionSetResult = selectionSetResult; SelectionSetData = new SelectionData[selectionSet.Selections.Count]; - ExportKeys = exportKeys; + Provides = provides; } /// @@ -28,14 +28,15 @@ public ExecutionState( /// /// Gets a list of keys representing the state that is being - /// exported while processing this work item. + /// provided after the associated + /// has been executed. /// - public IReadOnlyList ExportKeys { get; } + public IReadOnlyList Provides { get; } /// /// Gets the selection set that is being executed. /// - public ISelectionSet SelectionSet { get; } + public SelectionSet SelectionSet { get; } /// /// Gets the selection set data that was collected during execution. @@ -50,6 +51,5 @@ public ExecutionState( /// /// Gets a flag that indicates if the work item has been initialized. /// - /// public bool IsInitialized { get; set; } } diff --git a/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs b/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs index 5e8913bfe9e..b8fe4ec6837 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs @@ -474,7 +474,7 @@ public static void TryInitializeExecutionState(QueryPlan queryPlan, ExecutionSta partialResult, queryPlan, executionState.SelectionSet, - executionState.ExportKeys, + executionState.Provides, executionState.VariableValues); } diff --git a/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs b/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs index 2394b29ba0a..55e6960785b 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/FusionContextExtensions.cs @@ -6,7 +6,7 @@ internal static class FusionContextExtensions { public static ExecutionState RegisterState( this FusionExecutionContext context, - ISelectionSet selectionSet, + SelectionSet selectionSet, ObjectResult result, SelectionData parentData = default) { @@ -24,7 +24,7 @@ public static ExecutionState RegisterState( public static void TryRegisterState( this FusionExecutionContext context, - ISelectionSet selectionSet, + SelectionSet selectionSet, ObjectResult result, SelectionData parentData = default) { diff --git a/src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs b/src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs index 684fea80321..ce9ecbf0a8f 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/RequestState.cs @@ -8,10 +8,10 @@ namespace HotChocolate.Fusion.Execution; internal sealed class RequestState { - private readonly Dictionary> _map = new(); - private readonly HashSet _immutable = new(); + private readonly Dictionary> _map = new(); + private readonly HashSet _immutable = new(); - public bool ContainsState(ISelectionSet selectionSet) + public bool ContainsState(SelectionSet selectionSet) { var taken = false; Monitor.Enter(_map, ref taken); @@ -61,7 +61,7 @@ public bool ContainsState(SelectionSet[] selectionSets) } public bool TryGetState( - ISelectionSet selectionSet, + SelectionSet selectionSet, [NotNullWhen(true)] out List? values) { var taken = false; @@ -99,7 +99,7 @@ public bool TryGetState( } public void TryRegisterState( - ISelectionSet selectionSet, + SelectionSet selectionSet, ObjectResult result, IReadOnlyList exportKeys, SelectionData parentData) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs index 967b5ebad78..bdf6ee750ad 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs @@ -1,3 +1,4 @@ +using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; using HotChocolate.Fusion.Metadata; @@ -100,7 +101,7 @@ private void HandledSpecialQueryFields( { var introspectionNode = new Introspect( context.NextNodeId(), - context.Operation.RootSelectionSet); + Unsafe.As(context.Operation.RootSelectionSet)); context.RegisterNode(introspectionNode, executionStep); context.RegisterSelectionSet(context.Operation.RootSelectionSet); handled.Add(executionStep); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs index 5d1d2089a7d..20ae4506385 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs @@ -8,24 +8,66 @@ namespace HotChocolate.Fusion.Planning; +/// +/// The node composes the results of multiple selection sets. +/// internal sealed class Compose : QueryPlanNode { private readonly SelectionSet[] _selectionSets; - public Compose(int id, Resolve resolve) - : this(id, new[] { resolve.SelectionSet }) { } - + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// + /// Unique withing its query plan. + /// + /// + /// + /// The selection set for which the results shall be composed. + /// public Compose(int id, SelectionSet selectionSet) : this(id, new[] { selectionSet }) { } - public Compose(int id, IReadOnlyList selectionSets) : base(id) + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// + /// Unique withing its query plan. + /// + /// + /// + /// The selection sets for which the results shall be composed. + /// + public Compose(int id, IEnumerable selectionSets) : base(id) { ArgumentNullException.ThrowIfNull(selectionSets); _selectionSets = selectionSets.Distinct().OrderBy(t => t.Id).ToArray(); } + /// + /// Gets the kind of this node. + /// public override QueryPlanNodeKind Kind => QueryPlanNodeKind.Compose; + /// + /// Composes the results for the associated selection sets. + /// + /// + /// The execution context. + /// + /// + /// The GraphQL request state. + /// + /// + /// The cancellation token. + /// + /// + /// Returns the task representing the execution state. + /// protected override Task OnExecuteAsync( FusionExecutionContext context, RequestState state, @@ -63,6 +105,21 @@ protected override Task OnExecuteAsync( return Task.CompletedTask; } + /// + /// Executes the child nodes of this node. + /// + /// + /// The execution context. + /// + /// + /// The GraphQL request state. + /// + /// + /// The cancellation token. + /// + /// + /// Returns the task representing the execution state. + /// protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, RequestState state, @@ -84,14 +141,24 @@ protected override async Task OnExecuteNodesAsync( } } + /// + /// Formats this node to JSON. + /// + /// + /// The JSON writer. + /// protected override void FormatProperties(Utf8JsonWriter writer) { writer.WritePropertyName(SelectionSetIdsProp); writer.WriteStartArray(); - foreach (var selectionSet in _selectionSets) + ref var selectionSet = ref MemoryMarshal.GetArrayDataReference(_selectionSets); + ref var end = ref Unsafe.Add(ref selectionSet, _selectionSets.Length); + + while (Unsafe.IsAddressLessThan(ref selectionSet, ref end)) { writer.WriteNumberValue(selectionSet.Id); + selectionSet = ref Unsafe.Add(ref selectionSet, 1)!; } writer.WriteEndArray(); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs index e62f0936691..02798c8b810 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs @@ -3,16 +3,15 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution; using HotChocolate.Language; -using HotChocolate.Types.Introspection; -using HotChocolate.Utilities; +using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; internal sealed class Introspect : QueryPlanNode { - private readonly ISelectionSet _selectionSet; + private readonly SelectionSet _selectionSet; - public Introspect(int id, ISelectionSet selectionSet) : base(id) + public Introspect(int id, SelectionSet selectionSet) : base(id) { _selectionSet = selectionSet ?? throw new ArgumentNullException(nameof(selectionSet)); } @@ -66,6 +65,6 @@ protected override void FormatProperties(Utf8JsonWriter writer) } var selectionSetNode = new SelectionSetNode(null, rootSelectionNodes); - writer.WriteString("document", selectionSetNode.ToString(false)); + writer.WriteString(DocumentProp, selectionSetNode.ToString(false)); } } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs index e590d16f4df..e29e6bd7943 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using HotChocolate.Fusion.Execution; namespace HotChocolate.Fusion.Planning; @@ -13,6 +14,12 @@ protected override async Task OnExecuteNodesAsync( RequestState state, CancellationToken cancellationToken) { + if (Debugger.IsAttached) + { + await base.OnExecuteNodesAsync(context, state, cancellationToken).ConfigureAwait(false); + return; + } + var tasks = new Task[Nodes.Count]; for (var i = 0; i < Nodes.Count; i++) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs index 534e48c98f6..b1bef9d0a05 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs @@ -1,4 +1,5 @@ using System.Buffers; +using System.Runtime.CompilerServices; using System.Text; using System.Text.Json; using HotChocolate.Execution; @@ -7,6 +8,7 @@ using HotChocolate.Fusion.Execution; using HotChocolate.Language; using HotChocolate.Language.Visitors; +using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; @@ -95,7 +97,7 @@ public async Task ExecuteAsync( operationContext.Result.SetContextData("queryPlan", context.QueryPlan); // Enqueue root node to initiate the execution process. - var rootSelectionSet = context.Operation.RootSelectionSet; + var rootSelectionSet = Unsafe.As(context.Operation.RootSelectionSet); var rootResult = context.Result.RentObject(rootSelectionSet.Selections.Count); context.Result.SetData(rootResult); @@ -178,14 +180,14 @@ public void Format(Utf8JsonWriter writer) { writer.WriteStartObject(); - writer.WriteString("document", _operation.Document.ToString(false)); + writer.WriteString(DocumentProp, _operation.Document.ToString(false)); if (!string.IsNullOrEmpty(_operation.Name)) { - writer.WriteString("operation", _operation.Name); + writer.WriteString(OperationProp, _operation.Name); } - writer.WritePropertyName("rootNode"); + writer.WritePropertyName(RootNodeProp); RootNode.Format(writer); writer.WriteEndObject(); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs index c354ece8894..0c5b3eb6437 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs @@ -125,7 +125,7 @@ private void ProcessResponses( var data = UnwrapResult(response); var selectionSet = state.SelectionSet; var selectionResults = state.SelectionSetData; - var exportKeys = state.ExportKeys; + var exportKeys = state.Provides; var variableValues = state.VariableValues; ExtractErrors(context.Result, response.Errors, context.ShowDebugInfo); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs index fe438d584cf..9ad1852cf77 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs @@ -76,8 +76,6 @@ private void ProcessResult( GraphQLResponse response, BatchExecutionState[] batchExecutionState) { - var first = batchExecutionState[0]; - ExtractErrors(context.Result, response.Errors, context.ShowDebugInfo); var result = UnwrapResult(response, Requires); @@ -86,10 +84,10 @@ private void ProcessResult( while (Unsafe.IsAddressLessThan(ref batchState, ref end)) { - if (result.TryGetValue(batchState.Key, out var workItemData)) + if (result.TryGetValue(batchState.Key, out var data)) { - ExtractSelectionResults(SelectionSet, SubgraphName, workItemData, batchState.SelectionResults); - ExtractVariables(workItemData, context.QueryPlan, SelectionSet, first.ExportKeys, first.VariableValues); + ExtractSelectionResults(SelectionSet, SubgraphName, data, batchState.SelectionResults); + ExtractVariables(data, context.QueryPlan, SelectionSet, batchState.Provides, batchState.VariableValues); } batchState = ref Unsafe.Add(ref batchState, 1); @@ -100,9 +98,11 @@ private static Dictionary BuildVariables( BatchExecutionState[] batchExecutionState, Dictionary argumentTypes) { + var first = batchExecutionState[0]; + if (batchExecutionState.Length == 1) { - return batchExecutionState[0].VariableValues; + return first.VariableValues; } var variableValues = new Dictionary(); @@ -122,7 +122,7 @@ private static Dictionary BuildVariables( batchState = ref Unsafe.Add(ref batchState, 1); } - foreach (var key in batchExecutionState[0].VariableValues.Keys) + foreach (var key in first.VariableValues.Keys) { var expectedType = argumentTypes[key]; @@ -313,7 +313,7 @@ public BatchExecutionState( { Key = batchKey; VariableValues = executionState.VariableValues; - ExportKeys = executionState.ExportKeys; + Provides = executionState.Provides; SelectionResults = executionState.SelectionSetData; } @@ -321,7 +321,12 @@ public BatchExecutionState( public Dictionary VariableValues { get; } - public IReadOnlyList ExportKeys { get; } + /// + /// Gets a list of keys representing the state that is being + /// provided after the associated + /// has been executed. + /// + public IReadOnlyList Provides { get; } public SelectionData[] SelectionResults { get; } } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Sequence.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Sequence.cs index 4782f27a092..fa0ad998b3c 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Sequence.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Sequence.cs @@ -1,8 +1,22 @@ namespace HotChocolate.Fusion.Planning; +/// +/// The sequence node is responsible for executing +/// it's child nodes in a sequence one after the other. +/// internal sealed class Sequence : QueryPlanNode { + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// Unique withing its query plan. + /// public Sequence(int id) : base(id) { } + /// + /// Gets the kind of this node. + /// public override QueryPlanNodeKind Kind => QueryPlanNodeKind.Sequence; } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs index 5bce27cb89d..eeef7c0859f 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs @@ -90,7 +90,7 @@ internal async IAsyncEnumerable SubscribeAsync( initialResponse = false; // Before we can start building requests we need to rent state for the execution result. - var rootSelectionSet = context.Operation.RootSelectionSet; + var rootSelectionSet = Unsafe.As(context.Operation.RootSelectionSet); var rootResult = context.Result.RentObject(rootSelectionSet.Selections.Count); // by registering the state we will get a work item which represents the state for @@ -106,7 +106,7 @@ internal async IAsyncEnumerable SubscribeAsync( // So we skip execution and just unwrap the result and extract the selection data. var data = UnwrapResult(response); var selectionResults = workItem.SelectionSetData; - var exportKeys = workItem.ExportKeys; + var exportKeys = workItem.Provides; variableValues = workItem.VariableValues; // we extract the selection data from the request and add it to the workItem results. diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs index 1b1ef29a183..8a543b61f5d 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs @@ -9,6 +9,10 @@ internal static class Utf8QueryPlanPropertyNames public static ReadOnlySpan SubgraphProp => "subgraph"u8; public static ReadOnlySpan DocumentProp => "document"u8; + + public static ReadOnlySpan OperationProp => "operation"u8; + + public static ReadOnlySpan RootNodeProp => "rootNode"u8; public static ReadOnlySpan SelectionSetIdProp => "selectionSetId"u8; diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap index 76b257c3daa..aacec724dbd 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap @@ -135,11 +135,6 @@ QueryPlan Result --------------- { - "errors": [ - { - "message": "Unexpected Execution Error" - } - ], "data": { "reviews": [ { @@ -148,7 +143,13 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": {} + "product": { + "name": "Table", + "deliveryEstimate": { + "min": 400, + "max": 800 + } + } }, { "body": "Too expensive.", @@ -156,7 +157,13 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": {} + "product": { + "name": "Couch", + "deliveryEstimate": { + "min": 2650, + "max": 5300 + } + } }, { "body": "Could be better.", @@ -164,7 +171,13 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": {} + "product": { + "name": "Chair", + "deliveryEstimate": { + "min": 45, + "max": 90 + } + } }, { "body": "Prefer something else.", @@ -172,7 +185,13 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": {} + "product": { + "name": "Table", + "deliveryEstimate": { + "min": 400, + "max": 800 + } + } } ] } diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap index 1a455622fb9..27e87f19cf9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap @@ -134,11 +134,6 @@ QueryPlan Result --------------- { - "errors": [ - { - "message": "Unexpected Execution Error" - } - ], "data": { "reviews": [ { @@ -147,7 +142,12 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": {} + "product": { + "deliveryEstimate": { + "min": 400, + "max": 800 + } + } }, { "body": "Too expensive.", @@ -155,7 +155,12 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": {} + "product": { + "deliveryEstimate": { + "min": 2650, + "max": 5300 + } + } }, { "body": "Could be better.", @@ -163,7 +168,12 @@ Result "name": "@ada", "birthdate": "1815-12-10" }, - "product": {} + "product": { + "deliveryEstimate": { + "min": 45, + "max": 90 + } + } }, { "body": "Prefer something else.", @@ -171,7 +181,12 @@ Result "name": "@alan", "birthdate": "1912-06-23" }, - "product": {} + "product": { + "deliveryEstimate": { + "min": 400, + "max": 800 + } + } } ] } diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap index b515e670e06..82d91988f15 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap @@ -168,11 +168,6 @@ QueryPlan Result --------------- { - "errors": [ - { - "message": "Unexpected Execution Error" - } - ], "data": { "users": [ { @@ -187,7 +182,11 @@ Result "birthdate": "1815-12-10" }, "product": { - "id": "UHJvZHVjdAppMQ==" + "id": "UHJvZHVjdAppMQ==", + "name": "Table", + "deliveryEstimate": { + "max": 800 + } } }, { @@ -197,7 +196,11 @@ Result "birthdate": "1815-12-10" }, "product": { - "id": "UHJvZHVjdAppMw==" + "id": "UHJvZHVjdAppMw==", + "name": "Chair", + "deliveryEstimate": { + "max": 90 + } } } ] @@ -214,7 +217,11 @@ Result "birthdate": "1912-06-23" }, "product": { - "id": "UHJvZHVjdAppMg==" + "id": "UHJvZHVjdAppMg==", + "name": "Couch", + "deliveryEstimate": { + "max": 5300 + } } }, { @@ -224,7 +231,11 @@ Result "birthdate": "1912-06-23" }, "product": { - "id": "UHJvZHVjdAppMQ==" + "id": "UHJvZHVjdAppMQ==", + "name": "Table", + "deliveryEstimate": { + "max": 800 + } } } ] From 8c0c30f6020c9b8ce527a8f3e0b7d1add5f1e64b Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 11:37:09 +0200 Subject: [PATCH 06/17] edits --- .../Fusion/src/Core/Planning/Nodes/Parallel.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs index e29e6bd7943..e590d16f4df 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using HotChocolate.Fusion.Execution; namespace HotChocolate.Fusion.Planning; @@ -14,12 +13,6 @@ protected override async Task OnExecuteNodesAsync( RequestState state, CancellationToken cancellationToken) { - if (Debugger.IsAttached) - { - await base.OnExecuteNodesAsync(context, state, cancellationToken).ConfigureAwait(false); - return; - } - var tasks = new Task[Nodes.Count]; for (var i = 0; i < Nodes.Count; i++) From 2345b333fe4354afa5446e5889dd7eae7276c3d1 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 12:24:28 +0200 Subject: [PATCH 07/17] edits --- .../Core/Planning/ExportDefinitionRegistry.cs | 29 ++++++++++++++++--- ...ts.Authors_And_Reviews_Batch_Requests.snap | 5 ---- ...hors_And_Reviews_Query_GetUserReviews.snap | 5 ---- ...Authors_And_Reviews_Query_ReviewsUser.snap | 5 ---- ...egrationTests.Require_Data_In_Context.snap | 8 ----- ...rationTests.Require_Data_In_Context_2.snap | 8 ----- ...rationTests.Require_Data_In_Context_3.snap | 11 ------- ...Tests.Accounts_Offline_Author_NonNull.snap | 5 ---- ...ests.Accounts_Offline_Author_Nullable.snap | 5 ---- ..._Offline_Reviews_ListElement_Nullable.snap | 5 ---- ...ts.Query_Interface_List_With_Fragment.snap | 5 ---- ...ry_Interface_List_With_Fragment_Fetch.snap | 5 ---- .../RequestPlannerTests.Query_Plan_01.snap | 5 ---- ...estPlannerTests.Query_Plan_02_Aliases.snap | 10 ------- ...stPlannerTests.Query_Plan_19_Requires.snap | 8 ----- ...tPlannerTests.Query_Plan_20_DeepQuery.snap | 13 --------- ...n_21_Field_Requirement_Not_In_Context.snap | 8 ----- ...rTests.Query_Plan_23_Interfaces_Merge.snap | 5 ---- ...eld_Requirement_And_Fields_In_Context.snap | 8 ----- 19 files changed, 25 insertions(+), 128 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs index 6d1491b44dc..59220ba43e1 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExportDefinitionRegistry.cs @@ -2,16 +2,15 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Metadata; using HotChocolate.Language; +using Microsoft.AspNetCore.Mvc; namespace HotChocolate.Fusion.Planning; internal sealed class ExportDefinitionRegistry { + private readonly HashSet _temp = new(); private readonly Dictionary<(ISelectionSet, string), string> _stateKeyLookup = new(); - - private readonly Dictionary _exportLookup = - new(StringComparer.Ordinal); - + private readonly Dictionary _exportLookup = new(StringComparer.Ordinal); private readonly List _exports = new(); private readonly string _groupKey = "_fusion_exports_"; private int _stateId; @@ -134,4 +133,26 @@ public IEnumerable GetExportKeys(ExecutionStep executionStep) } } } + + public IEnumerable GetExportKeys(SelectionExecutionStep executionStep) + { + _temp.Clear(); + + if (executionStep.Variables.Count > 0) + { + foreach (var (_, key) in executionStep.Variables) + { + _temp.Add(key); + } + } + + foreach (var exportDefinition in _exports) + { + if (ReferenceEquals(exportDefinition.ExecutionStep, executionStep) && + _temp.Add(exportDefinition.StateKey)) + { + yield return exportDefinition.StateKey; + } + } + } } \ No newline at end of file diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap index 2edac77cc56..cf4e1e439a2 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap @@ -43,11 +43,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap index 270a525c5bd..11e823f4fc6 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap @@ -46,11 +46,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap index 5d7929c3b82..28bc8af4b6d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap @@ -69,11 +69,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap index aacec724dbd..a1fb35f2f49 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap @@ -57,11 +57,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__3" - } - ], "requires": [ { "variable": "__fusion_exports__3" @@ -82,9 +77,6 @@ QueryPlan }, { "variable": "__fusion_exports__2" - }, - { - "variable": "__fusion_exports__4" } ], "requires": [ diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap index 27e87f19cf9..1bb6d28cba2 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap @@ -56,11 +56,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__3" - } - ], "requires": [ { "variable": "__fusion_exports__3" @@ -81,9 +76,6 @@ QueryPlan }, { "variable": "__fusion_exports__2" - }, - { - "variable": "__fusion_exports__4" } ], "requires": [ diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap index 82d91988f15..4a576240803 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap @@ -57,9 +57,6 @@ QueryPlan "nodes" ], "provides": [ - { - "variable": "__fusion_exports__3" - }, { "variable": "__fusion_exports__4" }, @@ -90,11 +87,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__4" - } - ], "requires": [ { "variable": "__fusion_exports__4" @@ -115,9 +107,6 @@ QueryPlan }, { "variable": "__fusion_exports__2" - }, - { - "variable": "__fusion_exports__5" } ], "requires": [ diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap index 9e8a450d42f..f069a171484 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap @@ -43,11 +43,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap index efe546e4e0f..355f0f52ae1 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap @@ -43,11 +43,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap index 0e0fafc42bc..31a9be5b06c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap @@ -43,11 +43,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap index 6a705ba38c0..39e9a518125 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap @@ -47,11 +47,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap index 6a705ba38c0..39e9a518125 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap @@ -47,11 +47,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap index ddc824bb3d3..a2bc254062b 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap @@ -46,11 +46,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap index 43dfac45714..179da26edeb 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap @@ -61,11 +61,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" @@ -80,11 +75,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__2" - } - ], "requires": [ { "variable": "__fusion_exports__2" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap index 994f4a3397e..7b6a38c7ebd 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap @@ -57,11 +57,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__3" - } - ], "requires": [ { "variable": "__fusion_exports__3" @@ -82,9 +77,6 @@ QueryPlan }, { "variable": "__fusion_exports__2" - }, - { - "variable": "__fusion_exports__4" } ], "requires": [ diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap index 53a5737abb8..f1a4ec90377 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap @@ -55,9 +55,6 @@ QueryPlan "nodes" ], "provides": [ - { - "variable": "__fusion_exports__1" - }, { "variable": "__fusion_exports__2" }, @@ -88,11 +85,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__2" - } - ], "requires": [ { "variable": "__fusion_exports__2" @@ -107,11 +99,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__3" - } - ], "requires": [ { "variable": "__fusion_exports__3" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap index 1db0f756afb..7697e5cfd39 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap @@ -56,11 +56,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__3" - } - ], "requires": [ { "variable": "__fusion_exports__3" @@ -81,9 +76,6 @@ QueryPlan }, { "variable": "__fusion_exports__2" - }, - { - "variable": "__fusion_exports__4" } ], "requires": [ diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap index 895378bcc6d..3366474f19d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap @@ -47,11 +47,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__1" - } - ], "requires": [ { "variable": "__fusion_exports__1" diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap index 1c09e560443..b25a565a3ed 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap @@ -58,11 +58,6 @@ QueryPlan "path": [ "nodes" ], - "provides": [ - { - "variable": "__fusion_exports__3" - } - ], "requires": [ { "variable": "__fusion_exports__3" @@ -83,9 +78,6 @@ QueryPlan }, { "variable": "__fusion_exports__2" - }, - { - "variable": "__fusion_exports__4" } ], "requires": [ From b487fad163fd67593950f9b49b3bcbbe086dcd9c Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 16:53:38 +0200 Subject: [PATCH 08/17] edits --- .../AspNetCoreResources.Designer.cs | 100 ++++++++--------- .../Pipeline/MergeEntityMiddleware.cs | 2 +- .../src/Core/FusionResources.Designer.cs | 6 + .../Fusion/src/Core/FusionResources.resx | 3 + .../ExecutionNodeBuilderMiddleware.cs | 2 +- .../src/Core/Planning/Nodes/Parallel.cs | 37 ++++++- .../src/Core/Planning/Nodes/QueryPlan.cs | 30 +++++ .../Fusion/src/Core/Planning/Nodes/Resolve.cs | 2 +- .../Core/Planning/Nodes/ResolveByKeyBatch.cs | 44 +++++++- .../src/Core/Planning/Nodes/ResolveNode.cs | 103 +++++++++++------- .../Fusion/src/Core/ThrowHelper.cs | 3 + .../Fusion/src/Core/Utilities/ErrorHelper.cs | 10 ++ .../Utilities/Utf8QueryPlanPropertyNames.cs | 14 +++ 13 files changed, 254 insertions(+), 102 deletions(-) diff --git a/src/HotChocolate/AspNetCore/src/AspNetCore/Properties/AspNetCoreResources.Designer.cs b/src/HotChocolate/AspNetCore/src/AspNetCore/Properties/AspNetCoreResources.Designer.cs index df627343bb2..4bb7ca59886 100644 --- a/src/HotChocolate/AspNetCore/src/AspNetCore/Properties/AspNetCoreResources.Designer.cs +++ b/src/HotChocolate/AspNetCore/src/AspNetCore/Properties/AspNetCoreResources.Designer.cs @@ -9,21 +9,21 @@ namespace HotChocolate.AspNetCore.Properties { using System; - - + + [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [System.Diagnostics.DebuggerNonUserCodeAttribute()] [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class AspNetCoreResources { - + private static System.Resources.ResourceManager resourceMan; - + private static System.Globalization.CultureInfo resourceCulture; - + [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal AspNetCoreResources() { } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Resources.ResourceManager ResourceManager { get { @@ -34,7 +34,7 @@ internal static System.Resources.ResourceManager ResourceManager { return resourceMan; } } - + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] internal static System.Globalization.CultureInfo Culture { get { @@ -44,251 +44,245 @@ internal static System.Globalization.CultureInfo Culture { resourceCulture = value; } } - + internal static string ThrowHelper_DefaultHttpRequestParser_RequestIsEmpty { get { return ResourceManager.GetString("ThrowHelper_DefaultHttpRequestParser_RequestIsEmpty", resourceCulture); } } - + internal static string ThrowHelper_DefaultHttpRequestParser_QueryAndIdMissing { get { return ResourceManager.GetString("ThrowHelper_DefaultHttpRequestParser_QueryAndIdMissing", resourceCulture); } } - + internal static string ThrowHelper_DefaultHttpRequestParser_MaxRequestSizeExceeded { get { return ResourceManager.GetString("ThrowHelper_DefaultHttpRequestParser_MaxRequestSizeExceeded", resourceCulture); } } - + internal static string ThrowHelper_DataStartMessageHandler_RequestTypeNotSupported { get { return ResourceManager.GetString("ThrowHelper_DataStartMessageHandler_RequestTypeNotSupported", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_Invalid_Form { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_Invalid_Form", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_No_Operations_Specified { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_No_Operations_Specified", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_Fields_Misordered { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_Fields_Misordered", resourceCulture); } } - + internal static string HttpMultipartMiddleware_InsertFilesIntoRequest_VariablesImmutable { get { return ResourceManager.GetString("HttpMultipartMiddleware_InsertFilesIntoRequest_VariablesImmutable", resourceCulture); } } - + internal static string VariablePath_Parse_FirstSegmentMustBeKey { get { return ResourceManager.GetString("VariablePath_Parse_FirstSegmentMustBeKey", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_NoObjectPath { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_NoObjectPath", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_FileMissing { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_FileMissing", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_VariableNotFound { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_VariableNotFound", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_VariableStructureInvalid { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_VariableStructureInvalid", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_InvalidPath { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_InvalidPath", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_PathMustStartWithVariable { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_PathMustStartWithVariable", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_InvalidMapJson { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_InvalidMapJson", resourceCulture); } } - + internal static string ThrowHelper_HttpMultipartMiddleware_MapNotSpecified { get { return ResourceManager.GetString("ThrowHelper_HttpMultipartMiddleware_MapNotSpecified", resourceCulture); } } - + internal static string ErrorHelper_InvalidRequest { get { return ResourceManager.GetString("ErrorHelper_InvalidRequest", resourceCulture); } } - + internal static string ErrorHelper_RequestHasNoElements { get { return ResourceManager.GetString("ErrorHelper_RequestHasNoElements", resourceCulture); } } - + internal static string WebSocketSession_SessionEnded { get { return ResourceManager.GetString("WebSocketSession_SessionEnded", resourceCulture); } } - + internal static string DataStartMessageHandler_Not_A_SubscriptionResult { get { return ResourceManager.GetString("DataStartMessageHandler_Not_A_SubscriptionResult", resourceCulture); } } - + internal static string OperationMessage_TypeCannotBeNullOrEmpty { get { return ResourceManager.GetString("OperationMessage_TypeCannotBeNullOrEmpty", resourceCulture); } } - + internal static string TerminateConnectionMessageHandler_Message { get { return ResourceManager.GetString("TerminateConnectionMessageHandler_Message", resourceCulture); } } - + internal static string OperationManager_Register_SessionIdNullOrEmpty { get { return ResourceManager.GetString("OperationManager_Register_SessionIdNullOrEmpty", resourceCulture); } } - + internal static string Apollo_OnReceive_MessageMustBeJson { get { return ResourceManager.GetString("Apollo_OnReceive_MessageMustBeJson", resourceCulture); } } - + internal static string Apollo_OnReceive_TypePropMissing { get { return ResourceManager.GetString("Apollo_OnReceive_TypePropMissing", resourceCulture); } } - + internal static string Apollo_OnReceive_ToManyInitializations { get { return ResourceManager.GetString("Apollo_OnReceive_ToManyInitializations", resourceCulture); } } - + internal static string Apollo_OnReceive_InvalidSubscribeMessage { get { return ResourceManager.GetString("Apollo_OnReceive_InvalidSubscribeMessage", resourceCulture); } } - + internal static string Apollo_OnReceive_SubscriptionIdNotUnique { get { return ResourceManager.GetString("Apollo_OnReceive_SubscriptionIdNotUnique", resourceCulture); } } - + internal static string Apollo_OnReceive_InvalidMessageType { get { return ResourceManager.GetString("Apollo_OnReceive_InvalidMessageType", resourceCulture); } } - + internal static string ConnectionStatus_Reject_Message_cannot_be_null_or_empty_ { get { return ResourceManager.GetString("ConnectionStatus_Reject_Message_cannot_be_null_or_empty_", resourceCulture); } } - + internal static string ConnectionStatus_Reject_MessageCannotBeNullOrEmpty { get { return ResourceManager.GetString("ConnectionStatus_Reject_MessageCannotBeNullOrEmpty", resourceCulture); } } - + internal static string ErrorHelper_NoSupportedAcceptMediaType { get { return ResourceManager.GetString("ErrorHelper_NoSupportedAcceptMediaType", resourceCulture); } } - + internal static string ThrowHelper_Formatter_ResultKindNotSupported { get { return ResourceManager.GetString("ThrowHelper_Formatter_ResultKindNotSupported", resourceCulture); } } - + internal static string ThrowHelper_Formatter_ResponseContentTypeNotSupported { get { return ResourceManager.GetString("ThrowHelper_Formatter_ResponseContentTypeNotSupported", resourceCulture); } } - + internal static string ThrowHelper_Formatter_InvalidAcceptMediaType { get { return ResourceManager.GetString("ThrowHelper_Formatter_InvalidAcceptMediaType", resourceCulture); } } - + internal static string ErrorHelper_InvalidAcceptMediaType { get { return ResourceManager.GetString("ErrorHelper_InvalidAcceptMediaType", resourceCulture); } } - + internal static string ErrorHelper_TypeNotFound { get { return ResourceManager.GetString("ErrorHelper_TypeNotFound", resourceCulture); } } - + internal static string ErrorHelper_InvalidTypeName { get { return ResourceManager.GetString("ErrorHelper_InvalidTypeName", resourceCulture); } } - + internal static string ErrorHelper_TypeNameIsEmpty { get { return ResourceManager.GetString("ErrorHelper_TypeNameIsEmpty", resourceCulture); } } - - internal static string GraphQLHttpClient_InvalidContentType { - get { - return ResourceManager.GetString("GraphQLHttpClient_InvalidContentType", resourceCulture); - } - } } } diff --git a/src/HotChocolate/Fusion/src/Composition/Pipeline/MergeEntityMiddleware.cs b/src/HotChocolate/Fusion/src/Composition/Pipeline/MergeEntityMiddleware.cs index f23a507f804..84cfd94f523 100644 --- a/src/HotChocolate/Fusion/src/Composition/Pipeline/MergeEntityMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Composition/Pipeline/MergeEntityMiddleware.cs @@ -28,7 +28,7 @@ public async ValueTask InvokeAsync(CompositionContext context, MergeDelegate nex } } -static file class MergeEntitiesMiddlewareExtensions +file static class MergeEntitiesMiddlewareExtensions { public static void Merge(this CompositionContext context, EntityPart source, ObjectType target) { diff --git a/src/HotChocolate/Fusion/src/Core/FusionResources.Designer.cs b/src/HotChocolate/Fusion/src/Core/FusionResources.Designer.cs index e0201f87c06..ff048cba47c 100644 --- a/src/HotChocolate/Fusion/src/Core/FusionResources.Designer.cs +++ b/src/HotChocolate/Fusion/src/Core/FusionResources.Designer.cs @@ -146,5 +146,11 @@ internal static string ExecutionNodeBuilderMiddleware_CreateResolveByKeyBatchNod return ResourceManager.GetString("ExecutionNodeBuilderMiddleware_CreateResolveByKeyBatchNode_StateInconsistent", resourceCulture); } } + + internal static string ResolveNode_EntityResolver_Already_Registered { + get { + return ResourceManager.GetString("ResolveNode_EntityResolver_Already_Registered", resourceCulture); + } + } } } diff --git a/src/HotChocolate/Fusion/src/Core/FusionResources.resx b/src/HotChocolate/Fusion/src/Core/FusionResources.resx index a3f32374a88..c56832f9c3f 100644 --- a/src/HotChocolate/Fusion/src/Core/FusionResources.resx +++ b/src/HotChocolate/Fusion/src/Core/FusionResources.resx @@ -69,4 +69,7 @@ The state is inconsistent. + + The entity resolver for the specified type name was already registered. + diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs index bdf6ee750ad..0127724c0a3 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs @@ -79,7 +79,7 @@ private void HandledSpecialQueryFields( { var nodeResolverNode = new ResolveNode( context.NextNodeId(), - nodeStep.NodeSelection); + Unsafe.As(nodeStep.NodeSelection)); context.RegisterNode(nodeResolverNode, nodeStep); context.RegisterSelectionSet(context.Operation.RootSelectionSet); handled.Add(nodeStep); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs index e590d16f4df..21e6585c6e1 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs @@ -1,11 +1,25 @@ +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using HotChocolate.Fusion.Execution; namespace HotChocolate.Fusion.Planning; +/// +/// The node executes its child nodes in parallel. +/// internal sealed class Parallel : QueryPlanNode { + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// public Parallel(int id) : base(id) { } + /// + /// Gets the kind of this node. + /// public override QueryPlanNodeKind Kind => QueryPlanNodeKind.Parallel; protected override async Task OnExecuteNodesAsync( @@ -13,13 +27,24 @@ protected override async Task OnExecuteNodesAsync( RequestState state, CancellationToken cancellationToken) { - var tasks = new Task[Nodes.Count]; + InitializeNodes(context, cancellationToken, out var tasks); + await Task.WhenAll(tasks).ConfigureAwait(false); + } + + private void InitializeNodes(FusionExecutionContext context, CancellationToken cancellationToken, out Task[] tasks) + { + var nodes = Unsafe.As>(Nodes); + tasks = new Task[nodes.Count]; + + ref var node = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(nodes)); + ref var task = ref MemoryMarshal.GetArrayDataReference(tasks); + ref var end = ref Unsafe.Add(ref node, nodes.Count); - for (var i = 0; i < Nodes.Count; i++) + while (Unsafe.IsAddressLessThan(ref node, ref end)) { - tasks[i] = Nodes[i].ExecuteAsync(context, cancellationToken); + task = node.ExecuteAsync(context, cancellationToken); + node = ref Unsafe.Add(ref node, 1); + task = ref Unsafe.Add(ref task, 1); } - - await Task.WhenAll(tasks).ConfigureAwait(false); } -} +} \ No newline at end of file diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs index b1bef9d0a05..4c6c096af10 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs @@ -17,6 +17,7 @@ internal sealed class QueryPlan private readonly IOperation _operation; private readonly Dictionary _exportKeysLookup = new(); private readonly Dictionary<(ISelectionSet, string), string[]> _exportPathsLookup = new(); + private readonly (string Key, string DisplayName)[] _exportKeyToVariableName; private readonly IReadOnlySet _selectionSets; public QueryPlan( @@ -44,6 +45,18 @@ public QueryPlan( _exportPathsLookup.Add((exportGroup.Key, export.StateKey), context.Path.ToArray()); } } + + var index = 0; + _exportKeyToVariableName = new (string, string)[exports.Count]; + + foreach (var export in exports) + { + _exportKeyToVariableName[index++] = (export.StateKey, export.VariableDefinition.Name); + } + } + else + { + _exportKeyToVariableName = Array.Empty<(string, string)>(); } } @@ -190,6 +203,23 @@ public void Format(Utf8JsonWriter writer) writer.WritePropertyName(RootNodeProp); RootNode.Format(writer); + if (_exportKeyToVariableName.Length > 0) + { + writer.WritePropertyName(StateProp); + + writer.WriteStartArray(); + + foreach (var (key, displayName) in _exportKeyToVariableName) + { + writer.WriteStartObject(); + writer.WriteString(VariableProp, key); + writer.WriteString(NameProp, displayName); + writer.WriteEndObject(); + } + + writer.WriteEndArray(); + } + writer.WriteEndObject(); } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs index 0c5b3eb6437..9be61f87cb8 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs @@ -7,7 +7,7 @@ namespace HotChocolate.Fusion.Planning; /// -/// The resolver node is responsible for executing a GraphQL request on a subgraph. +/// The resolver node is responsible for fetching data from a subgraph. /// internal sealed class Resolve : ResolverNodeBase { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs index 9ad1852cf77..ae5b58841fd 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs @@ -9,18 +9,48 @@ namespace HotChocolate.Fusion.Planning; +/// +/// The resolver node is responsible for batch fetching data from a subgraph. +/// internal sealed class ResolveByKeyBatch : ResolverNodeBase { private readonly Dictionary _argumentTypes; + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// + /// + /// Gets the resolver configuration. + /// + /// + /// The argument types that are required to build the batch request. + /// public ResolveByKeyBatch(int id, Config config, IReadOnlyDictionary argumentTypes) : base(id, config) { _argumentTypes = new Dictionary(argumentTypes, StringComparer.Ordinal); } + /// + /// Gets the kind of this node. + /// public override QueryPlanNodeKind Kind => QueryPlanNodeKind.ResolveByKeyBatch; + /// + /// Executes this resolver node. + /// + /// + /// The execution context. + /// + /// + /// The execution state. + /// + /// + /// The cancellation token. + /// protected override async Task OnExecuteAsync( FusionExecutionContext context, RequestState state, @@ -47,7 +77,19 @@ protected override async Task OnExecuteAsync( ProcessResult(context, response, batchExecutionState); } } - + + /// + /// Executes this resolver node. + /// + /// + /// The execution context. + /// + /// + /// The execution state. + /// + /// + /// The cancellation token. + /// protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, RequestState state, diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs index e3d09aa0f82..c71544a5aed 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs @@ -5,22 +5,51 @@ using HotChocolate.Language; using HotChocolate.Resolvers; using HotChocolate.Types.Relay; +using static HotChocolate.Fusion.FusionResources; +using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using static HotChocolate.Fusion.Utilities.ErrorHelper; namespace HotChocolate.Fusion.Planning; +/// +/// The resolver node is responsible for fetching nodes from subgraphs. +/// internal sealed class ResolveNode : QueryPlanNode { private readonly Dictionary _fetchNodes = new(StringComparer.Ordinal); - - public ResolveNode(int id, ISelection selection) : base(id) + private readonly Selection _selection; + + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// + /// + /// The selection that shall be resolved. + /// + public ResolveNode(int id, Selection selection) : base(id) { - Selection = selection; + _selection = selection; } + /// + /// Gets the kind of this node. + /// public override QueryPlanNodeKind Kind => QueryPlanNodeKind.ResolveNode; - public ISelection Selection { get; } - + /// + /// Executes this resolver node. + /// + /// + /// The execution context. + /// + /// + /// The execution state. + /// + /// + /// The cancellation token. + /// protected override async Task OnExecuteNodesAsync( FusionExecutionContext context, RequestState state, @@ -29,19 +58,13 @@ protected override async Task OnExecuteNodesAsync( var variables = context.OperationContext.Variables; var coercedArguments = new Dictionary(); - Selection.Arguments.CoerceArguments(variables, coercedArguments); + _selection.Arguments.CoerceArguments(variables, coercedArguments); var idArgument = coercedArguments["id"]; if (idArgument.ValueLiteral is not StringValueNode formattedId) { - // TODO : ERROR HELPER - context.Result.AddError( - ErrorBuilder.New() - .SetMessage("Node id format is invalid!") - .AddLocation(Selection.SyntaxNode) - .Build(), - Selection); + context.Result.AddError(InvalidNodeFormat(_selection), _selection); return; } @@ -53,38 +76,42 @@ protected override async Task OnExecuteNodesAsync( } catch (IdSerializationException ex) { - // TODO : ERROR HELPER - context.Result.AddError( - ErrorBuilder.New() - .SetMessage("Node id format is invalid 2!") - .AddLocation(Selection.SyntaxNode) - .SetException(ex) - .Build(), - Selection); + context.Result.AddError(InvalidNodeFormat(_selection, ex), _selection); return; } if(!_fetchNodes.TryGetValue(idValue.TypeName, out var fetchNode)) { - // TODO : ERROR HELPER - context.Result.AddError( - ErrorBuilder.New() - .SetMessage("The id is invalid 3!") - .AddLocation(Selection.SyntaxNode) - .Build(), - Selection); + context.Result.AddError(InvalidNodeFormat(_selection), _selection); return; } await fetchNode.ExecuteAsync(context, cancellationToken).ConfigureAwait(false); } + /// + /// Registers an entity resolver. + /// + /// + /// The name of the entity type for which the resolver shall be registered. + /// + /// + /// The resolver that shall be registered. + /// + /// + /// The node is read-only. + /// + /// + /// or is null. + /// + /// + /// A resolver for the specified is already registered. + /// public void AddEntityResolver(string typeName, Resolve resolveEntity) { if(IsReadOnly) { - // TODO : ERROR HELPER - throw new InvalidOperationException("The execution node is read-only."); + throw ThrowHelper.Node_ReadOnly(); } if (typeName is null) @@ -99,23 +126,22 @@ public void AddEntityResolver(string typeName, Resolve resolveEntity) if (_fetchNodes.ContainsKey(typeName)) { - // TODO : ERROR HELPER throw new ArgumentException( - "A fetch node for this entity type already exists.", + ResolveNode_EntityResolver_Already_Registered, paramName: nameof(typeName)); } _fetchNodes.Add(typeName, resolveEntity); base.AddNode(resolveEntity); } - + internal override void AddNode(QueryPlanNode node) => throw new NotSupportedException(); protected override void FormatProperties(Utf8JsonWriter writer) { - writer.WriteNumber("selectionId", Selection.Id); - writer.WriteString("responseName", Selection.ResponseName); + writer.WriteNumber(SelectionIdProp, _selection.Id); + writer.WriteString(ResponseNameProp, _selection.ResponseName); base.FormatProperties(writer); } @@ -123,15 +149,14 @@ protected override void FormatNodesProperty(Utf8JsonWriter writer) { if (_fetchNodes.Count > 0) { - writer.WritePropertyName("branches"); - + writer.WritePropertyName(BranchesProp); writer.WriteStartArray(); foreach (var (type, node) in _fetchNodes) { writer.WriteStartObject(); - writer.WriteString("type", type); - writer.WritePropertyName("node"); + writer.WriteString(TypeProp, type); + writer.WritePropertyName(NodeProp); node.Format(writer); writer.WriteEndObject(); } diff --git a/src/HotChocolate/Fusion/src/Core/ThrowHelper.cs b/src/HotChocolate/Fusion/src/Core/ThrowHelper.cs index 10f05bdae7b..1165dfbec4c 100644 --- a/src/HotChocolate/Fusion/src/Core/ThrowHelper.cs +++ b/src/HotChocolate/Fusion/src/Core/ThrowHelper.cs @@ -76,4 +76,7 @@ public static SchemaException UnableToLoadConfiguration() SchemaErrorBuilder.New() .SetMessage("Unable to load the Fusion gateway configuration.") .Build()); + + public static InvalidOperationException Node_ReadOnly() + => new("The execution node is read-only."); } diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/ErrorHelper.cs b/src/HotChocolate/Fusion/src/Core/Utilities/ErrorHelper.cs index 34a0815b304..c94d772111e 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/ErrorHelper.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/ErrorHelper.cs @@ -1,4 +1,5 @@ using HotChocolate.Execution; +using HotChocolate.Execution.Processing; namespace HotChocolate.Fusion.Utilities; @@ -9,4 +10,13 @@ public static IQueryResult IncrementalDelivery_NotSupported() => ErrorBuilder.New() .SetMessage("Incremental delivery is not yet supported.") .Build()); + + public static IError InvalidNodeFormat( + ISelection selection, + Exception? exception = null) + => ErrorBuilder.New() + .SetMessage("The id value has an invalid format.") + .AddLocation(selection.SyntaxNode) + .SetException(exception) + .Build(); } diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs index 8a543b61f5d..c672582c5b4 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs @@ -23,4 +23,18 @@ internal static class Utf8QueryPlanPropertyNames public static ReadOnlySpan VariableProp => "variable"u8; public static ReadOnlySpan ForwardedVariablesProp => "forwardedVariables"u8; + + public static ReadOnlySpan StateProp => "state"u8; + + public static ReadOnlySpan NameProp => "name"u8; + + public static ReadOnlySpan BranchesProp => "branches"u8; + + public static ReadOnlySpan TypeProp => "type"u8; + + public static ReadOnlySpan NodeProp => "node"u8; + + public static ReadOnlySpan SelectionIdProp => "selectionId"u8; + + public static ReadOnlySpan ResponseNameProp => "responseName"u8; } \ No newline at end of file From 61040d5a6a124d3e8cd66430ed6e8d90dd0cfcf2 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 16:56:07 +0200 Subject: [PATCH 09/17] edits --- .../src/Core/Planning/Nodes/Parallel.cs | 4 ++-- ...eviews_And_Products_Query_TopProducts.snap | 8 ++++++- ...d_Reviews_And_Products_Query_TypeName.snap | 8 ++++++- ...ts.Authors_And_Reviews_Batch_Requests.snap | 8 ++++++- ...hors_And_Reviews_Query_GetUserReviews.snap | 8 ++++++- ...Authors_And_Reviews_Query_ReviewsUser.snap | 8 ++++++- ...er_With_Node_Field_From_Two_Subgraphs.snap | 8 ++++++- ...er_With_Node_Field_Pass_In_Unknown_Id.snap | 2 +- ...egrationTests.Require_Data_In_Context.snap | 20 +++++++++++++++- ...rationTests.Require_Data_In_Context_2.snap | 20 +++++++++++++++- ...rationTests.Require_Data_In_Context_3.snap | 24 ++++++++++++++++++- ...Tests.Accounts_Offline_Author_NonNull.snap | 8 ++++++- ...ests.Accounts_Offline_Author_Nullable.snap | 8 ++++++- ..._Offline_Reviews_ListElement_Nullable.snap | 8 ++++++- ...ts.Query_Interface_List_With_Fragment.snap | 8 ++++++- ...ry_Interface_List_With_Fragment_Fetch.snap | 8 ++++++- .../RequestPlannerTests.Query_Plan_01.snap | 8 ++++++- ...estPlannerTests.Query_Plan_02_Aliases.snap | 12 +++++++++- ...nerTests.Query_Plan_05_TypeName_Field.snap | 8 ++++++- ...ry_Plan_10_Two_Mutation_Same_SubGraph.snap | 12 +++++++++- ...ery_Plan_11_Two_Mutation_Two_SubGraph.snap | 12 +++++++++- ...nerTests.Query_Plan_13_Subscription_2.snap | 8 ++++++- ...de_Single_Fragment_Multiple_Subgraphs.snap | 8 ++++++- ...de_Single_Fragment_Multiple_Subgraphs.snap | 12 +++++++++- ...stPlannerTests.Query_Plan_19_Requires.snap | 20 +++++++++++++++- ...tPlannerTests.Query_Plan_20_DeepQuery.snap | 16 ++++++++++++- ...n_21_Field_Requirement_Not_In_Context.snap | 20 +++++++++++++++- ...rTests.Query_Plan_23_Interfaces_Merge.snap | 8 ++++++- ...eld_Requirement_And_Fields_In_Context.snap | 20 +++++++++++++++- ..._Plan_25_Variables_Are_Passed_Through.snap | 8 ++++++- 30 files changed, 299 insertions(+), 31 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs index 21e6585c6e1..e1e8e4edc71 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs @@ -43,8 +43,8 @@ private void InitializeNodes(FusionExecutionContext context, CancellationToken c while (Unsafe.IsAddressLessThan(ref node, ref end)) { task = node.ExecuteAsync(context, cancellationToken); - node = ref Unsafe.Add(ref node, 1); - task = ref Unsafe.Add(ref task, 1); + node = ref Unsafe.Add(ref node, 1)!; + task = ref Unsafe.Add(ref task, 1)!; } } } \ No newline at end of file diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap index 15bd18aad9c..13fcb3e3cc0 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap @@ -59,7 +59,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap index c485ba1c9f2..e07326ac140 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap @@ -69,7 +69,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap index cf4e1e439a2..a653892f3d8 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap @@ -56,7 +56,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap index 11e823f4fc6..6616234a149 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap @@ -59,7 +59,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap index 28bc8af4b6d..1a6c900c3e9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap @@ -82,7 +82,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap index d435fa0c561..c9544d9be1d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap @@ -96,7 +96,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap index 8500ea16013..9c3aa7e0a50 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap @@ -82,7 +82,7 @@ Result { "errors": [ { - "message": "The id is invalid 3!", + "message": "The id value has an invalid format.", "locations": [ { "line": 2, diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap index a1fb35f2f49..247873182f5 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap @@ -120,7 +120,25 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_dimension_size" + }, + { + "variable": "__fusion_exports__2", + "name": "Product_dimension_weight" + }, + { + "variable": "__fusion_exports__3", + "name": "User_id" + }, + { + "variable": "__fusion_exports__4", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap index 1bb6d28cba2..829ada21bf0 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap @@ -119,7 +119,25 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_dimension_size" + }, + { + "variable": "__fusion_exports__2", + "name": "Product_dimension_weight" + }, + { + "variable": "__fusion_exports__3", + "name": "User_id" + }, + { + "variable": "__fusion_exports__4", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap index 4a576240803..dde568e6167 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap @@ -150,7 +150,29 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_dimension_size" + }, + { + "variable": "__fusion_exports__2", + "name": "Product_dimension_weight" + }, + { + "variable": "__fusion_exports__3", + "name": "User_id" + }, + { + "variable": "__fusion_exports__4", + "name": "User_id" + }, + { + "variable": "__fusion_exports__5", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap index f069a171484..77b3c19bff2 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap @@ -56,7 +56,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap index 355f0f52ae1..97d9ed4ccc5 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap @@ -56,7 +56,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap index 31a9be5b06c..eb8cfe347d9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap @@ -56,7 +56,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap index 39e9a518125..f2ca5f3bc7c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap @@ -60,7 +60,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Patient1_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap index 39e9a518125..f2ca5f3bc7c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap @@ -60,7 +60,13 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Patient1_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap index a2bc254062b..eec85db61cf 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_01.snap @@ -59,6 +59,12 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap index 179da26edeb..65d87ea3d3d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_02_Aliases.snap @@ -91,6 +91,16 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + }, + { + "variable": "__fusion_exports__2", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap index 9427ea8bf88..819f8529101 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_05_TypeName_Field.snap @@ -69,6 +69,12 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap index 38c9eca4844..ad606cf7c27 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_10_Two_Mutation_Same_SubGraph.snap @@ -90,6 +90,16 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + }, + { + "variable": "__fusion_exports__2", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap index f0de2624345..ac2733bbc09 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_11_Two_Mutation_Two_SubGraph.snap @@ -96,6 +96,16 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + }, + { + "variable": "__fusion_exports__2", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap index 136b4ed8549..db4a5cfcae7 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_13_Subscription_2.snap @@ -59,6 +59,12 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_15_Node_Single_Fragment_Multiple_Subgraphs.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_15_Node_Single_Fragment_Multiple_Subgraphs.snap index 92976ab1e8f..a40fc19accc 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_15_Node_Single_Fragment_Multiple_Subgraphs.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_15_Node_Single_Fragment_Multiple_Subgraphs.snap @@ -82,6 +82,12 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_18_Node_Single_Fragment_Multiple_Subgraphs.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_18_Node_Single_Fragment_Multiple_Subgraphs.snap index 30697d0f6c5..f9b80d3ec66 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_18_Node_Single_Fragment_Multiple_Subgraphs.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_18_Node_Single_Fragment_Multiple_Subgraphs.snap @@ -108,6 +108,16 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + }, + { + "variable": "__fusion_exports__2", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap index 7b6a38c7ebd..e0571e4f445 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_19_Requires.snap @@ -120,6 +120,24 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_dimension_size" + }, + { + "variable": "__fusion_exports__2", + "name": "Product_dimension_weight" + }, + { + "variable": "__fusion_exports__3", + "name": "User_id" + }, + { + "variable": "__fusion_exports__4", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap index f1a4ec90377..3af62cf24ea 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_20_DeepQuery.snap @@ -115,6 +115,20 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "User_id" + }, + { + "variable": "__fusion_exports__2", + "name": "User_id" + }, + { + "variable": "__fusion_exports__3", + "name": "User_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap index 7697e5cfd39..eeca17a98bf 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_21_Field_Requirement_Not_In_Context.snap @@ -119,6 +119,24 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_dimension_size" + }, + { + "variable": "__fusion_exports__2", + "name": "Product_dimension_weight" + }, + { + "variable": "__fusion_exports__3", + "name": "User_id" + }, + { + "variable": "__fusion_exports__4", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap index 3366474f19d..7265389ca06 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_23_Interfaces_Merge.snap @@ -60,6 +60,12 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Patient1_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap index b25a565a3ed..c2f973f2b94 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_24_Field_Requirement_And_Fields_In_Context.snap @@ -121,6 +121,24 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Product_dimension_size" + }, + { + "variable": "__fusion_exports__2", + "name": "Product_dimension_weight" + }, + { + "variable": "__fusion_exports__3", + "name": "User_id" + }, + { + "variable": "__fusion_exports__4", + "name": "Product_id" + } + ] } --------------- diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap index 440249f8924..5a3a7a67e22 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/RequestPlannerTests.Query_Plan_25_Variables_Are_Passed_Through.snap @@ -63,6 +63,12 @@ QueryPlan ] } ] - } + }, + "state": [ + { + "variable": "__fusion_exports__1", + "name": "Patient1_id" + } + ] } --------------- From 6bd50feaa9c1bd52e5504191a0eb632dc6e57837 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 17:33:10 +0200 Subject: [PATCH 10/17] edits --- .../Fusion/src/Core/Planning/Nodes/If.cs | 22 ++++-- .../src/Core/Planning/Nodes/Introspect.cs | 44 +++++++++-- .../src/Core/Planning/Nodes/Parallel.cs | 8 +- .../src/Core/Planning/Nodes/QueryPlan.cs | 76 ++++++++++++++++++- .../src/Core/Planning/Nodes/QueryPlanNode.cs | 63 +++++++++++---- .../Core/Planning/Nodes/QueryPlanNodeKind.cs | 38 ++++++++++ .../src/Core/Planning/Nodes/Subscribe.cs | 1 - .../src/Core/Planning/QueryPlanContext.cs | 3 +- .../Utilities/Utf8QueryPlanPropertyNames.cs | 2 + 9 files changed, 223 insertions(+), 34 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs index 409f7f8cc92..988fe87aa7d 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs @@ -1,17 +1,30 @@ using System.Collections.Concurrent; using System.Text.Json; using HotChocolate.Fusion.Execution; +using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; +/// +/// The node is responsible for executing a node based on a state. +/// internal sealed class If : QueryPlanNode { private readonly List _branches = new(); + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// public If(int id) : base(id) { } + /// + /// Gets the kind of this node. + /// public override QueryPlanNodeKind Kind => QueryPlanNodeKind.If; protected override Task OnExecuteNodesAsync( @@ -49,8 +62,7 @@ public void AddBranch(string key, object value, QueryPlanNode node) { if (IsReadOnly) { - // TODO : error helper - throw new InvalidOperationException("The execution node is read-only."); + throw ThrowHelper.Node_ReadOnly(); } if (key is null) @@ -70,13 +82,11 @@ public void AddBranch(string key, object value, QueryPlanNode node) internal override void AddNode(QueryPlanNode node) => throw new NotSupportedException(); - public readonly record struct Branch(string Key, object Value, QueryPlanNode Node); - protected override void FormatNodesProperty(Utf8JsonWriter writer) { if (_branches.Count > 0) { - writer.WritePropertyName("branches"); + writer.WritePropertyName(BranchesProp); writer.WriteStartArray(); @@ -93,4 +103,6 @@ protected override void FormatNodesProperty(Utf8JsonWriter writer) writer.WriteEndArray(); } } + + private readonly record struct Branch(string Key, object Value, QueryPlanNode Node); } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs index 02798c8b810..e86d6714361 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs @@ -1,4 +1,5 @@ using System.Collections.Immutable; +using System.Runtime.CompilerServices; using System.Text.Json; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution; @@ -7,17 +8,47 @@ namespace HotChocolate.Fusion.Planning; +/// +/// The node is responsible for executing introspection selection of the GraphQL request. +/// internal sealed class Introspect : QueryPlanNode { private readonly SelectionSet _selectionSet; + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// + /// + /// The selection set for which the results shall be composed. + /// + /// + /// is null. + /// public Introspect(int id, SelectionSet selectionSet) : base(id) { _selectionSet = selectionSet ?? throw new ArgumentNullException(nameof(selectionSet)); } + /// + /// Gets the kind of this node. + /// public override QueryPlanNodeKind Kind => QueryPlanNodeKind.Introspect; + /// + /// Executes the introspection selections of the GraphQL request. + /// + /// + /// The execution context. + /// + /// + /// The execution state. + /// + /// + /// The cancellation token. + /// protected override async Task OnExecuteAsync( FusionExecutionContext context, RequestState state, @@ -25,9 +56,9 @@ protected override async Task OnExecuteAsync( { if (state.TryGetState(_selectionSet, out var values)) { + var value = values[0]; var operationContext = context.OperationContext; var rootSelections = _selectionSet.Selections; - var value = values.Single(); for (var i = 0; i < rootSelections.Count; i++) { @@ -53,15 +84,18 @@ protected override async Task OnExecuteAsync( protected override void FormatProperties(Utf8JsonWriter writer) { var rootSelectionNodes = new List(); - var rootSelections = _selectionSet.Selections; + var rootSelectionSet = Unsafe.As(_selectionSet); + ref var selection = ref rootSelectionSet.GetSelectionsReference(); + ref var end = ref Unsafe.Add(ref selection, rootSelectionSet.Selections.Count); - for (var i = 0; i < rootSelections.Count; i++) + while (Unsafe.IsAddressLessThan(ref selection, ref end)) { - var selection = rootSelections[i]; if (selection.Field.IsIntrospectionField) { - rootSelectionNodes.Add(rootSelections[i].SyntaxNode); + rootSelectionNodes.Add(selection.SyntaxNode); } + + selection = ref Unsafe.Add(ref selection, 1); } var selectionSetNode = new SelectionSetNode(null, rootSelectionNodes); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs index e1e8e4edc71..ec28f1d1ea6 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs @@ -33,12 +33,12 @@ protected override async Task OnExecuteNodesAsync( private void InitializeNodes(FusionExecutionContext context, CancellationToken cancellationToken, out Task[] tasks) { - var nodes = Unsafe.As>(Nodes); - tasks = new Task[nodes.Count]; + var nodes = GetNodesSpan(); + tasks = new Task[nodes.Length]; - ref var node = ref MemoryMarshal.GetReference(CollectionsMarshal.AsSpan(nodes)); + ref var node = ref MemoryMarshal.GetReference(nodes); ref var task = ref MemoryMarshal.GetArrayDataReference(tasks); - ref var end = ref Unsafe.Add(ref node, nodes.Count); + ref var end = ref Unsafe.Add(ref node, nodes.Length); while (Unsafe.IsAddressLessThan(ref node, ref end)) { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs index 4c6c096af10..61959fa82e2 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs @@ -12,6 +12,9 @@ namespace HotChocolate.Fusion.Planning; +/// +/// Represents a query plan that describes how a GraphQL request shall be executed. +/// internal sealed class QueryPlan { private readonly IOperation _operation; @@ -20,15 +23,35 @@ internal sealed class QueryPlan private readonly (string Key, string DisplayName)[] _exportKeyToVariableName; private readonly IReadOnlySet _selectionSets; + /// + /// Initializes a new instance of . + /// + /// + /// The operation for which the query plan was created. + /// + /// + /// The root node of the query plan. + /// + /// + /// The selection sets that are part of the query plan. + /// + /// + /// The exports that are part of the query plan. + /// public QueryPlan( IOperation operation, QueryPlanNode rootNode, IReadOnlySet selectionSets, IReadOnlyCollection exports) { - _operation = operation; - RootNode = rootNode; - _selectionSets = selectionSets; + if (exports == null) + { + throw new ArgumentNullException(nameof(exports)); + } + + _operation = operation ?? throw new ArgumentNullException(nameof(operation)); + RootNode = rootNode ?? throw new ArgumentNullException(nameof(rootNode)); + _selectionSets = selectionSets ?? throw new ArgumentNullException(nameof(selectionSets)); if (exports.Count > 0) { @@ -60,6 +83,9 @@ public QueryPlan( } } + /// + /// Gets the root node of the query plan. + /// public QueryPlanNode RootNode { get; } /// @@ -75,7 +101,7 @@ public QueryPlan( /// public bool HasNodesFor(ISelectionSet selectionSet) => _selectionSets.Contains(selectionSet); - + public IReadOnlyList GetExportKeys(ISelectionSet selectionSet) => _exportKeysLookup.TryGetValue(selectionSet, out var keys) ? keys @@ -86,10 +112,31 @@ public IReadOnlyList GetExportPath(ISelectionSet selectionSet, string ke ? path : Array.Empty(); + /// + /// Executes the query plan. + /// + /// + /// The execution context. + /// + /// + /// The cancellation token. + /// + /// + /// Returns the query result. + /// + /// + /// The query plan represents a subscription request + /// and cannot be executed but must be subscribed to. + /// public async Task ExecuteAsync( FusionExecutionContext context, CancellationToken cancellationToken) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + if (RootNode is Subscribe) { throw ThrowHelper.SubscriptionsMustSubscribe(); @@ -158,10 +205,31 @@ public async Task ExecuteAsync( return context.Result.BuildResult(); } + /// + /// Executes a subscription query plan. + /// + /// + /// The execution context. + /// + /// + /// The cancellation token. + /// + /// + /// Returns a response stream that represents the subscription result. + /// + /// + /// The query plan represents a query or mutation request + /// and cannot be subscribed to but must be executed. + /// public Task SubscribeAsync( FusionExecutionContext context, CancellationToken cancellationToken) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + if (RootNode is not Subscribe subscriptionNode) { throw ThrowHelper.QueryAndMutationMustExecute(); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs index 09b053c6710..11fa38a8da8 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs @@ -1,24 +1,47 @@ +using System.Runtime.InteropServices; using System.Text.Json; using HotChocolate.Fusion.Execution; +using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; +/// +/// The base class for all query plan nodes. +/// internal abstract class QueryPlanNode { private readonly List _nodes = new(); private bool _isReadOnly; + /// + /// Initializes a new instance of . + /// + /// + /// The unique id of this node. + /// protected QueryPlanNode(int id) { Id = id; } + /// + /// Gets the unique id of this node. + /// public int Id { get; } + /// + /// Gets the kind of this node. + /// public abstract QueryPlanNodeKind Kind { get; } + /// + /// Gets the child nodes of this node. + /// public IReadOnlyList Nodes => _nodes; + /// + /// Gets a value indicating whether this node is read-only. + /// private protected bool IsReadOnly => _isReadOnly; internal async Task ExecuteAsync( @@ -67,11 +90,19 @@ internal virtual void AddNode(QueryPlanNode node) internal void Seal() { - if (!_isReadOnly) + if (_isReadOnly) + { + return; + } + + OnSeal(); + + foreach (var node in Nodes) { - OnSeal(); - _isReadOnly = true; + node.Seal(); } + + _isReadOnly = true; } protected virtual void OnSeal() { } @@ -79,7 +110,7 @@ protected virtual void OnSeal() { } internal void Format(Utf8JsonWriter writer) { writer.WriteStartObject(); - writer.WriteString("type", Kind.ToString()); + writer.WriteString(TypeProp, Kind.ToString()); FormatProperties(writer); FormatNodesProperty(writer); writer.WriteEndObject(); @@ -91,18 +122,22 @@ protected virtual void FormatProperties(Utf8JsonWriter writer) protected virtual void FormatNodesProperty(Utf8JsonWriter writer) { - if (_nodes.Count > 0) + if (_nodes.Count <= 0) { - writer.WritePropertyName("nodes"); - - writer.WriteStartArray(); - - foreach (var node in _nodes) - { - node.Format(writer); - } + return; + } + + writer.WritePropertyName(NodesProp); + writer.WriteStartArray(); - writer.WriteEndArray(); + foreach (var node in _nodes) + { + node.Format(writer); } + + writer.WriteEndArray(); } + + protected ReadOnlySpan GetNodesSpan() + => CollectionsMarshal.AsSpan(_nodes); } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNodeKind.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNodeKind.cs index 838c984d6e3..77b5552bc8c 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNodeKind.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNodeKind.cs @@ -1,14 +1,52 @@ namespace HotChocolate.Fusion.Planning; +/// +/// Represents the query plan node kinds. +/// internal enum QueryPlanNodeKind { + /// + /// The node executes its child nodes in parallel. + /// Parallel, + + /// + /// The node executes its child nodes sequentially. + /// Sequence, + + /// + /// The resolver node is responsible for fetching data from a subgraph. + /// Resolve, + + /// + /// The resolver node is responsible for batch fetching data from a subgraph. + /// ResolveByKeyBatch, + + /// + /// The resolver node is responsible for fetching nodes from subgraphs. + /// ResolveNode, + + /// + /// A subscribe represents a subscription operation that is executed on a subgraph. + /// Subscribe, + + /// + /// The introspection node is responsible for fetching the schema from a subgraph. + /// Introspect, + + /// + /// The node composes the results of multiple selection sets. + /// Compose, + + /// + /// The node executes its child nodes based on a condition. + /// If } diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs index eeef7c0859f..77247acd4c5 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs @@ -4,7 +4,6 @@ using HotChocolate.Execution.DependencyInjection; using HotChocolate.Execution.Processing; using HotChocolate.Execution.Serialization; -using HotChocolate.Fusion.Clients; using HotChocolate.Fusion.Execution; using HotChocolate.Language; using Microsoft.Extensions.DependencyInjection; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs index cf8d8bc001a..33ea7cc78da 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs @@ -190,7 +190,8 @@ public QueryPlan BuildQueryPlan() throw new InvalidOperationException( "In order to build a query plan a root node must be set."); } - + + _rootNode.Seal(); return new QueryPlan(Operation, _rootNode, _selectionSets, Exports.All); } } diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs index c672582c5b4..1f8d0b408ee 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs @@ -34,6 +34,8 @@ internal static class Utf8QueryPlanPropertyNames public static ReadOnlySpan NodeProp => "node"u8; + public static ReadOnlySpan NodesProp => "nodes"u8; + public static ReadOnlySpan SelectionIdProp => "selectionId"u8; public static ReadOnlySpan ResponseNameProp => "responseName"u8; From abde22cd5bfd41d0072dbe46c489c2c816f930e8 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 17:36:50 +0200 Subject: [PATCH 11/17] edits --- src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs index e86d6714361..b638cfbb27b 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs @@ -95,7 +95,7 @@ protected override void FormatProperties(Utf8JsonWriter writer) rootSelectionNodes.Add(selection.SyntaxNode); } - selection = ref Unsafe.Add(ref selection, 1); + selection = ref Unsafe.Add(ref selection, 1)!; } var selectionSetNode = new SelectionSetNode(null, rootSelectionNodes); From f50b3361b723c787d400ec3504bd5e43fc71aa28 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 17:38:05 +0200 Subject: [PATCH 12/17] edits --- .../FusionRequestExecutorBuilderExtensions.cs | 2 +- .../Core/DependencyInjection/GatewayConfigurationTypeModule.cs | 1 + .../Fusion/src/Core/Metadata/FusionGraphConfigurationReader.cs | 2 +- .../src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs | 1 + .../src/Core/Planning/FieldRequirementsPlannerMiddleware.cs | 1 + src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs | 2 +- src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs | 3 ++- src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs | 2 +- src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs | 3 ++- .../Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs | 2 +- src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs | 3 ++- .../Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs | 1 + .../Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs | 3 ++- .../Planning/RequestFormatters/NodeRequestDocumentFormatter.cs | 1 + .../Planning/RequestFormatters/RequestDocumentFormatter.cs | 1 + src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs | 2 +- .../Fusion/src/Core/{ => Utilities}/ThrowHelper.cs | 3 +-- .../Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs | 2 +- 18 files changed, 22 insertions(+), 13 deletions(-) rename src/HotChocolate/Fusion/src/Core/{ => Utilities}/ThrowHelper.cs (97%) diff --git a/src/HotChocolate/Fusion/src/Core/DependencyInjection/FusionRequestExecutorBuilderExtensions.cs b/src/HotChocolate/Fusion/src/Core/DependencyInjection/FusionRequestExecutorBuilderExtensions.cs index 8a7bb9dd547..5f0f1d24bd1 100644 --- a/src/HotChocolate/Fusion/src/Core/DependencyInjection/FusionRequestExecutorBuilderExtensions.cs +++ b/src/HotChocolate/Fusion/src/Core/DependencyInjection/FusionRequestExecutorBuilderExtensions.cs @@ -9,7 +9,7 @@ using HotChocolate.Language; using HotChocolate.Types.Descriptors; using Microsoft.Extensions.DependencyInjection.Extensions; -using static HotChocolate.Fusion.ThrowHelper; +using static HotChocolate.Fusion.Utilities.ThrowHelper; // ReSharper disable once CheckNamespace namespace Microsoft.Extensions.DependencyInjection; diff --git a/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs b/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs index ef52129c95f..b595ea3db99 100644 --- a/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs +++ b/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs @@ -3,6 +3,7 @@ using HotChocolate.Fusion; using HotChocolate.Fusion.Configuration; using HotChocolate.Fusion.Metadata; +using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Types; using HotChocolate.Types.Descriptors.Definitions; diff --git a/src/HotChocolate/Fusion/src/Core/Metadata/FusionGraphConfigurationReader.cs b/src/HotChocolate/Fusion/src/Core/Metadata/FusionGraphConfigurationReader.cs index 231428a9e57..ceec5c00488 100644 --- a/src/HotChocolate/Fusion/src/Core/Metadata/FusionGraphConfigurationReader.cs +++ b/src/HotChocolate/Fusion/src/Core/Metadata/FusionGraphConfigurationReader.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.DependencyInjection; using static HotChocolate.Fusion.FusionDirectiveArgumentNames; using static HotChocolate.Fusion.FusionResources; -using static HotChocolate.Fusion.ThrowHelper; +using static HotChocolate.Fusion.Utilities.ThrowHelper; using static HotChocolate.Language.Utf8GraphQLParser.Syntax; namespace HotChocolate.Fusion.Metadata; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs index 050cefd9b66..d58246ccbf9 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs @@ -2,6 +2,7 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Metadata; +using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Types; using HotChocolate.Types.Introspection; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/FieldRequirementsPlannerMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/FieldRequirementsPlannerMiddleware.cs index 46a24783037..3a2aa9a69a1 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/FieldRequirementsPlannerMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/FieldRequirementsPlannerMiddleware.cs @@ -1,6 +1,7 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Metadata; +using HotChocolate.Fusion.Utilities; using HotChocolate.Utilities; using static System.StringComparer; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs index 20ae4506385..5da90a42121 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs @@ -4,7 +4,7 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution; using static HotChocolate.Fusion.Execution.ExecutorUtils; -using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs index 988fe87aa7d..fb072273303 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs @@ -1,7 +1,8 @@ using System.Collections.Concurrent; using System.Text.Json; using HotChocolate.Fusion.Execution; -using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using HotChocolate.Fusion.Utilities; +using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs index b638cfbb27b..730cb862495 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs @@ -4,7 +4,7 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution; using HotChocolate.Language; -using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs index 61959fa82e2..1ce0d1ee74b 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs @@ -8,7 +8,8 @@ using HotChocolate.Fusion.Execution; using HotChocolate.Language; using HotChocolate.Language.Visitors; -using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; +using ThrowHelper = HotChocolate.Fusion.Utilities.ThrowHelper; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs index 11fa38a8da8..a10441476de 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs @@ -1,7 +1,7 @@ using System.Runtime.InteropServices; using System.Text.Json; using HotChocolate.Fusion.Execution; -using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs index c71544a5aed..28989b0a181 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs @@ -2,11 +2,12 @@ using HotChocolate.Execution.Internal; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution; +using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Resolvers; using HotChocolate.Types.Relay; using static HotChocolate.Fusion.FusionResources; -using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; using static HotChocolate.Fusion.Utilities.ErrorHelper; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs index d22cf816df5..f063f54ca8c 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs @@ -2,6 +2,7 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; +using HotChocolate.Fusion.Utilities; using HotChocolate.Language; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs index cfe9a9fb3b0..3b5c322e4cc 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs @@ -5,7 +5,8 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; using HotChocolate.Language; -using static HotChocolate.Fusion.Planning.Utf8QueryPlanPropertyNames; +using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; +using ThrowHelper = HotChocolate.Fusion.Utilities.ThrowHelper; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs index 6f169e72625..ae42b9bd11d 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/NodeRequestDocumentFormatter.cs @@ -2,6 +2,7 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Metadata; +using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Types; using HotChocolate.Types.Introspection; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs index 9956498b63b..2d7adc1aafc 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/RequestFormatters/RequestDocumentFormatter.cs @@ -2,6 +2,7 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Metadata; +using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Language.Visitors; using HotChocolate.Resolvers; diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs b/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs index 747513c527a..f2144df4a78 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/CollectionUtils.cs @@ -1,6 +1,6 @@ using System.Buffers; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Utilities; internal static class CollectionUtils { diff --git a/src/HotChocolate/Fusion/src/Core/ThrowHelper.cs b/src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs similarity index 97% rename from src/HotChocolate/Fusion/src/Core/ThrowHelper.cs rename to src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs index 1165dfbec4c..24bca647156 100644 --- a/src/HotChocolate/Fusion/src/Core/ThrowHelper.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs @@ -1,8 +1,7 @@ -using System.Runtime.CompilerServices; using HotChocolate.Language; using static HotChocolate.Fusion.FusionResources; -namespace HotChocolate.Fusion; +namespace HotChocolate.Fusion.Utilities; internal static class ThrowHelper { diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs index 1f8d0b408ee..8480746b088 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/Utf8QueryPlanPropertyNames.cs @@ -1,4 +1,4 @@ -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Utilities; internal static class Utf8QueryPlanPropertyNames { From c2cd9e12a53ace9891f47f371521a10ec1380a51 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 17:40:37 +0200 Subject: [PATCH 13/17] edits --- .../Core/DependencyInjection/GatewayConfigurationTypeModule.cs | 1 - .../Core/{Configuration => Metadata}/ConfigurationRewriter.cs | 3 +-- .../Core/{Configuration => Metadata}/IConfigurationRewriter.cs | 2 +- .../src/Core/{ => Metadata}/ServiceConfigurationException.cs | 2 +- src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs | 1 + .../Fusion/test/Core.Tests/ConfigurationRewriterTests.cs | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) rename src/HotChocolate/Fusion/src/Core/{Configuration => Metadata}/ConfigurationRewriter.cs (98%) rename src/HotChocolate/Fusion/src/Core/{Configuration => Metadata}/IConfigurationRewriter.cs (93%) rename src/HotChocolate/Fusion/src/Core/{ => Metadata}/ServiceConfigurationException.cs (94%) diff --git a/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs b/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs index b595ea3db99..2de3fd36f78 100644 --- a/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs +++ b/src/HotChocolate/Fusion/src/Core/DependencyInjection/GatewayConfigurationTypeModule.cs @@ -1,7 +1,6 @@ using HotChocolate; using HotChocolate.Execution.Configuration; using HotChocolate.Fusion; -using HotChocolate.Fusion.Configuration; using HotChocolate.Fusion.Metadata; using HotChocolate.Fusion.Utilities; using HotChocolate.Language; diff --git a/src/HotChocolate/Fusion/src/Core/Configuration/ConfigurationRewriter.cs b/src/HotChocolate/Fusion/src/Core/Metadata/ConfigurationRewriter.cs similarity index 98% rename from src/HotChocolate/Fusion/src/Core/Configuration/ConfigurationRewriter.cs rename to src/HotChocolate/Fusion/src/Core/Metadata/ConfigurationRewriter.cs index dd0a1463a7e..3534cfdd42f 100644 --- a/src/HotChocolate/Fusion/src/Core/Configuration/ConfigurationRewriter.cs +++ b/src/HotChocolate/Fusion/src/Core/Metadata/ConfigurationRewriter.cs @@ -1,7 +1,6 @@ -using HotChocolate.Fusion.Metadata; using HotChocolate.Language; -namespace HotChocolate.Fusion.Configuration; +namespace HotChocolate.Fusion.Metadata; /// /// This base class allows to rewrite the gateway configuration before it is applied. diff --git a/src/HotChocolate/Fusion/src/Core/Configuration/IConfigurationRewriter.cs b/src/HotChocolate/Fusion/src/Core/Metadata/IConfigurationRewriter.cs similarity index 93% rename from src/HotChocolate/Fusion/src/Core/Configuration/IConfigurationRewriter.cs rename to src/HotChocolate/Fusion/src/Core/Metadata/IConfigurationRewriter.cs index 97409cabfdb..d474504222c 100644 --- a/src/HotChocolate/Fusion/src/Core/Configuration/IConfigurationRewriter.cs +++ b/src/HotChocolate/Fusion/src/Core/Metadata/IConfigurationRewriter.cs @@ -1,6 +1,6 @@ using HotChocolate.Language; -namespace HotChocolate.Fusion.Configuration; +namespace HotChocolate.Fusion.Metadata; /// /// This interface allows to rewrite the gateway configuration before it is applied. diff --git a/src/HotChocolate/Fusion/src/Core/ServiceConfigurationException.cs b/src/HotChocolate/Fusion/src/Core/Metadata/ServiceConfigurationException.cs similarity index 94% rename from src/HotChocolate/Fusion/src/Core/ServiceConfigurationException.cs rename to src/HotChocolate/Fusion/src/Core/Metadata/ServiceConfigurationException.cs index e1151512e53..6c119229d75 100644 --- a/src/HotChocolate/Fusion/src/Core/ServiceConfigurationException.cs +++ b/src/HotChocolate/Fusion/src/Core/Metadata/ServiceConfigurationException.cs @@ -1,6 +1,6 @@ using System.Runtime.Serialization; -namespace HotChocolate.Fusion; +namespace HotChocolate.Fusion.Metadata; [Serializable] public class ServiceConfigurationException : Exception diff --git a/src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs b/src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs index 24bca647156..ff68d929812 100644 --- a/src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs +++ b/src/HotChocolate/Fusion/src/Core/Utilities/ThrowHelper.cs @@ -1,3 +1,4 @@ +using HotChocolate.Fusion.Metadata; using HotChocolate.Language; using static HotChocolate.Fusion.FusionResources; diff --git a/src/HotChocolate/Fusion/test/Core.Tests/ConfigurationRewriterTests.cs b/src/HotChocolate/Fusion/test/Core.Tests/ConfigurationRewriterTests.cs index 2d4a9f6a161..bb032ac5e02 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/ConfigurationRewriterTests.cs +++ b/src/HotChocolate/Fusion/test/Core.Tests/ConfigurationRewriterTests.cs @@ -2,7 +2,7 @@ using HotChocolate.Execution; using HotChocolate.Execution.Configuration; using HotChocolate.Fusion.Composition; -using HotChocolate.Fusion.Configuration; +using HotChocolate.Fusion.Metadata; using HotChocolate.Fusion.Planning; using HotChocolate.Fusion.Shared; using HotChocolate.Language; From a4d5f2e6df9ecb98ac6fc28fc111f3c2b9306dd6 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 17:44:00 +0200 Subject: [PATCH 14/17] edits --- .../QueryPlanSnapshotValueFormatter.cs | 1 + .../Fusion/src/Core/Execution/Argument.cs | 16 ---------------- .../Fusion/src/Core/Execution/ExecutorUtils.cs | 4 ++-- .../src/Core/Execution/FederatedQueryContext.cs | 1 + .../{Planning => Execution}/Nodes/Compose.cs | 3 +-- .../src/Core/{Planning => Execution}/Nodes/If.cs | 3 +-- .../{Planning => Execution}/Nodes/Introspect.cs | 3 +-- .../{Planning => Execution}/Nodes/Parallel.cs | 3 +-- .../{Planning => Execution}/Nodes/QueryPlan.cs | 4 ++-- .../Nodes/QueryPlanNode.cs | 3 +-- .../Nodes/QueryPlanNodeKind.cs | 2 +- .../Nodes/ReformatVariableRewriter.cs | 2 +- .../{Planning => Execution}/Nodes/Resolve.cs | 3 +-- .../Nodes/ResolveByKeyBatch.cs | 3 +-- .../{Planning => Execution}/Nodes/ResolveNode.cs | 3 +-- .../Nodes/ResolverNodeBase.Config.cs | 2 +- .../Nodes/ResolverNodeBase.cs | 2 +- .../{Planning => Execution}/Nodes/Sequence.cs | 2 +- .../{Planning => Execution}/Nodes/Subscribe.cs | 3 +-- .../Pipeline/OperationExecutionMiddleware.cs | 1 + .../Planning/ExecutionNodeBuilderMiddleware.cs | 1 + .../Planning/ExecutionTreeBuilderMiddleware.cs | 2 ++ .../Fusion/src/Core/Planning/NodeAndStep.cs | 2 ++ .../Fusion/src/Core/Planning/QueryPlanContext.cs | 1 + .../Fusion/src/Core/Planning/QueryPlanner.cs | 1 + .../test/Core.Tests/RequestPlannerTests.cs | 2 +- .../Fusion/test/Core.Tests/TestHelper.cs | 1 + 27 files changed, 30 insertions(+), 44 deletions(-) delete mode 100644 src/HotChocolate/Fusion/src/Core/Execution/Argument.cs rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/Compose.cs (98%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/If.cs (97%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/Introspect.cs (97%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/Parallel.cs (95%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/QueryPlan.cs (99%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/QueryPlanNode.cs (97%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/QueryPlanNodeKind.cs (96%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/ReformatVariableRewriter.cs (94%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/Resolve.cs (98%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/ResolveByKeyBatch.cs (99%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/ResolveNode.cs (98%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/ResolverNodeBase.Config.cs (98%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/ResolverNodeBase.cs (99%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/Sequence.cs (92%) rename src/HotChocolate/Fusion/src/Core/{Planning => Execution}/Nodes/Subscribe.cs (98%) diff --git a/src/CookieCrumble/src/CookieCrumble/Formatters/QueryPlanSnapshotValueFormatter.cs b/src/CookieCrumble/src/CookieCrumble/Formatters/QueryPlanSnapshotValueFormatter.cs index b367c05cd71..29772d89ea2 100644 --- a/src/CookieCrumble/src/CookieCrumble/Formatters/QueryPlanSnapshotValueFormatter.cs +++ b/src/CookieCrumble/src/CookieCrumble/Formatters/QueryPlanSnapshotValueFormatter.cs @@ -1,5 +1,6 @@ #if NET7_0_OR_GREATER using System.Buffers; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Planning; namespace CookieCrumble.Formatters; diff --git a/src/HotChocolate/Fusion/src/Core/Execution/Argument.cs b/src/HotChocolate/Fusion/src/Core/Execution/Argument.cs deleted file mode 100644 index 3277edc5269..00000000000 --- a/src/HotChocolate/Fusion/src/Core/Execution/Argument.cs +++ /dev/null @@ -1,16 +0,0 @@ -using HotChocolate.Language; - -namespace HotChocolate.Fusion.Execution; - -internal readonly struct Argument -{ - public Argument(string name, IValueNode value) - { - Name = name; - Value = value; - } - - public string Name { get; } - - public IValueNode Value { get; } -} diff --git a/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs b/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs index b8fe4ec6837..e3f868fc887 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs @@ -3,8 +3,8 @@ using System.Runtime.InteropServices; using System.Text.Json; using HotChocolate.Execution.Processing; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Metadata; -using HotChocolate.Fusion.Planning; using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Types; @@ -27,7 +27,7 @@ public static void ComposeResult( ExecutionState executionState) => ComposeResult( context, - (SelectionSet)executionState.SelectionSet, + executionState.SelectionSet, executionState.SelectionSetData, executionState.SelectionSetResult); diff --git a/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs b/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs index 262d5215a83..c093c3d0eef 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/FederatedQueryContext.cs @@ -1,6 +1,7 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Metadata; using HotChocolate.Fusion.Planning; using HotChocolate.Types.Relay; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Compose.cs similarity index 98% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/Compose.cs index 5da90a42121..5c74235818b 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Compose.cs @@ -2,11 +2,10 @@ using System.Runtime.InteropServices; using System.Text.Json; using HotChocolate.Execution.Processing; -using HotChocolate.Fusion.Execution; using static HotChocolate.Fusion.Execution.ExecutorUtils; using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The node composes the results of multiple selection sets. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/If.cs similarity index 97% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/If.cs index fb072273303..ecfc980ad8e 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/If.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/If.cs @@ -1,10 +1,9 @@ using System.Collections.Concurrent; using System.Text.Json; -using HotChocolate.Fusion.Execution; using HotChocolate.Fusion.Utilities; using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The node is responsible for executing a node based on a state. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Introspect.cs similarity index 97% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/Introspect.cs index 730cb862495..eb6862d2c4c 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Introspect.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Introspect.cs @@ -2,11 +2,10 @@ using System.Runtime.CompilerServices; using System.Text.Json; using HotChocolate.Execution.Processing; -using HotChocolate.Fusion.Execution; using HotChocolate.Language; using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The node is responsible for executing introspection selection of the GraphQL request. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Parallel.cs similarity index 95% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/Parallel.cs index ec28f1d1ea6..1c104df38dc 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Parallel.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Parallel.cs @@ -1,8 +1,7 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using HotChocolate.Fusion.Execution; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The node executes its child nodes in parallel. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs index 1ce0d1ee74b..032742a9c42 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlan.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs @@ -5,13 +5,13 @@ using HotChocolate.Execution; using HotChocolate.Execution.Processing; using HotChocolate.Execution.Serialization; -using HotChocolate.Fusion.Execution; +using HotChocolate.Fusion.Planning; using HotChocolate.Language; using HotChocolate.Language.Visitors; using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; using ThrowHelper = HotChocolate.Fusion.Utilities.ThrowHelper; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// Represents a query plan that describes how a GraphQL request shall be executed. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlanNode.cs similarity index 97% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlanNode.cs index a10441476de..84da4989768 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlanNode.cs @@ -1,9 +1,8 @@ using System.Runtime.InteropServices; using System.Text.Json; -using HotChocolate.Fusion.Execution; using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The base class for all query plan nodes. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNodeKind.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlanNodeKind.cs similarity index 96% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNodeKind.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlanNodeKind.cs index 77b5552bc8c..d688204f9d1 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/QueryPlanNodeKind.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlanNodeKind.cs @@ -1,4 +1,4 @@ -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// Represents the query plan node kinds. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ReformatVariableRewriter.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ReformatVariableRewriter.cs similarity index 94% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/ReformatVariableRewriter.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/ReformatVariableRewriter.cs index 1c9bf753fea..adcdcd4d8af 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ReformatVariableRewriter.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ReformatVariableRewriter.cs @@ -3,7 +3,7 @@ using HotChocolate.Transport.Http; using HotChocolate.Types; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; internal sealed class ReformatVariableRewriter : SyntaxRewriter, ISyntaxVisitorContext { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Resolve.cs similarity index 98% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/Resolve.cs index 9be61f87cb8..9b1e6c094d8 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Resolve.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Resolve.cs @@ -1,10 +1,9 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using HotChocolate.Fusion.Clients; -using HotChocolate.Fusion.Execution; using static HotChocolate.Fusion.Execution.ExecutorUtils; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The resolver node is responsible for fetching data from a subgraph. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs index ae5b58841fd..657c8275dd3 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveByKeyBatch.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs @@ -3,11 +3,10 @@ using System.Text; using System.Text.Json; using HotChocolate.Fusion.Clients; -using HotChocolate.Fusion.Execution; using HotChocolate.Language; using static HotChocolate.Fusion.Execution.ExecutorUtils; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The resolver node is responsible for batch fetching data from a subgraph. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveNode.cs similarity index 98% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveNode.cs index 28989b0a181..7b93e8a0168 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolveNode.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveNode.cs @@ -1,7 +1,6 @@ using System.Text.Json; using HotChocolate.Execution.Internal; using HotChocolate.Execution.Processing; -using HotChocolate.Fusion.Execution; using HotChocolate.Fusion.Utilities; using HotChocolate.Language; using HotChocolate.Resolvers; @@ -10,7 +9,7 @@ using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; using static HotChocolate.Fusion.Utilities.ErrorHelper; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The resolver node is responsible for fetching nodes from subgraphs. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.Config.cs similarity index 98% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.Config.cs index f063f54ca8c..bccecc5ef27 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.Config.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.Config.cs @@ -5,7 +5,7 @@ using HotChocolate.Fusion.Utilities; using HotChocolate.Language; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; internal abstract partial class ResolverNodeBase { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.cs index 3b5c322e4cc..ed907624fa1 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/ResolverNodeBase.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolverNodeBase.cs @@ -8,7 +8,7 @@ using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; using ThrowHelper = HotChocolate.Fusion.Utilities.ThrowHelper; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The resolver node is responsible for executing a GraphQL request on a subgraph. diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Sequence.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Sequence.cs similarity index 92% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/Sequence.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/Sequence.cs index fa0ad998b3c..28cb5304b84 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Sequence.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Sequence.cs @@ -1,4 +1,4 @@ -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// The sequence node is responsible for executing diff --git a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Subscribe.cs similarity index 98% rename from src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs rename to src/HotChocolate/Fusion/src/Core/Execution/Nodes/Subscribe.cs index 77247acd4c5..e7d7a1d7e97 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/Nodes/Subscribe.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Subscribe.cs @@ -4,13 +4,12 @@ using HotChocolate.Execution.DependencyInjection; using HotChocolate.Execution.Processing; using HotChocolate.Execution.Serialization; -using HotChocolate.Fusion.Execution; using HotChocolate.Language; using Microsoft.Extensions.DependencyInjection; using static HotChocolate.Fusion.Execution.ExecutorUtils; using static HotChocolate.WellKnownContextData; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Execution.Nodes; /// /// A subscribe represents a subscription operation that is executed on a subgraph. diff --git a/src/HotChocolate/Fusion/src/Core/Pipeline/OperationExecutionMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Pipeline/OperationExecutionMiddleware.cs index 79c644d8d23..03550e1f127 100644 --- a/src/HotChocolate/Fusion/src/Core/Pipeline/OperationExecutionMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Pipeline/OperationExecutionMiddleware.cs @@ -4,6 +4,7 @@ using HotChocolate.Fetching; using HotChocolate.Fusion.Clients; using HotChocolate.Fusion.Execution; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Metadata; using HotChocolate.Fusion.Planning; using HotChocolate.Language; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs index 0127724c0a3..140d71d98d9 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs @@ -1,6 +1,7 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Clients; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Metadata; using HotChocolate.Language; using HotChocolate.Types; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs index 8d581b0bd8f..e44d7436912 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs @@ -1,7 +1,9 @@ using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Language; using HotChocolate.Utilities; +using Parallel = HotChocolate.Fusion.Execution.Nodes.Parallel; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/NodeAndStep.cs b/src/HotChocolate/Fusion/src/Core/Planning/NodeAndStep.cs index 3024bc4619b..fe4dd41a3f6 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/NodeAndStep.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/NodeAndStep.cs @@ -1,3 +1,5 @@ +using HotChocolate.Fusion.Execution.Nodes; + namespace HotChocolate.Fusion.Planning; internal readonly record struct NodeAndStep(QueryPlanNode Node, ExecutionStep Step); diff --git a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs index 33ea7cc78da..cb2edb9c710 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanContext.cs @@ -1,5 +1,6 @@ using System.Diagnostics.CodeAnalysis; using HotChocolate.Execution.Processing; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Language; using HotChocolate.Types; diff --git a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs index ce397cb1b41..d1487388193 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs @@ -1,4 +1,5 @@ using HotChocolate.Execution.Processing; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Metadata; namespace HotChocolate.Fusion.Planning; diff --git a/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs b/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs index b72380fdd5b..cb863592a9a 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs +++ b/src/HotChocolate/Fusion/test/Core.Tests/RequestPlannerTests.cs @@ -1016,7 +1016,7 @@ query Appointments($first: Int!) { await snapshot.MatchAsync(); } - private static async Task<(DocumentNode UserRequest, QueryPlan QueryPlan)> CreateQueryPlanAsync( + private static async Task<(DocumentNode UserRequest, Execution.Nodes.QueryPlan QueryPlan)> CreateQueryPlanAsync( Skimmed.Schema fusionGraph, [StringSyntax("graphql")] string query) { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs b/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs index 8d7659f2f5e..23a8236b4e4 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs +++ b/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs @@ -1,5 +1,6 @@ using CookieCrumble; using HotChocolate.Execution; +using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Planning; using HotChocolate.Language; using HotChocolate.Skimmed.Serialization; From e68dc899adc8161de15400857a74a21776cec4f4 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 17:46:31 +0200 Subject: [PATCH 15/17] edits --- .../Planning/{ => Pipeline}/ExecutionNodeBuilderMiddleware.cs | 2 +- .../{ => Pipeline}/ExecutionStepDiscoveryMiddleware.cs | 2 +- .../Planning/{ => Pipeline}/ExecutionTreeBuilderMiddleware.cs | 2 +- .../{ => Pipeline}/FieldRequirementsPlannerMiddleware.cs | 3 +-- .../Planning/{ => Pipeline}/RequirementsPlannerMiddleware.cs | 2 +- src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs | 1 + 6 files changed, 6 insertions(+), 6 deletions(-) rename src/HotChocolate/Fusion/src/Core/Planning/{ => Pipeline}/ExecutionNodeBuilderMiddleware.cs (99%) rename src/HotChocolate/Fusion/src/Core/Planning/{ => Pipeline}/ExecutionStepDiscoveryMiddleware.cs (99%) rename src/HotChocolate/Fusion/src/Core/Planning/{ => Pipeline}/ExecutionTreeBuilderMiddleware.cs (99%) rename src/HotChocolate/Fusion/src/Core/Planning/{ => Pipeline}/FieldRequirementsPlannerMiddleware.cs (99%) rename src/HotChocolate/Fusion/src/Core/Planning/{ => Pipeline}/RequirementsPlannerMiddleware.cs (99%) diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionNodeBuilderMiddleware.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs rename to src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionNodeBuilderMiddleware.cs index 140d71d98d9..50e6d92d824 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionNodeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionNodeBuilderMiddleware.cs @@ -9,7 +9,7 @@ using static HotChocolate.Fusion.FusionResources; using static HotChocolate.Fusion.Metadata.ResolverKind; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Planning.Pipeline; internal sealed class ExecutionNodeBuilderMiddleware : IQueryPlanMiddleware { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionStepDiscoveryMiddleware.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs rename to src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionStepDiscoveryMiddleware.cs index d58246ccbf9..2b550010141 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionStepDiscoveryMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionStepDiscoveryMiddleware.cs @@ -8,7 +8,7 @@ using HotChocolate.Types.Introspection; using HotChocolate.Utilities; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Planning.Pipeline; /// /// The request planer will rewrite the into diff --git a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionTreeBuilderMiddleware.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs rename to src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionTreeBuilderMiddleware.cs index e44d7436912..fb81e8b9f9e 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/ExecutionTreeBuilderMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/ExecutionTreeBuilderMiddleware.cs @@ -5,7 +5,7 @@ using HotChocolate.Utilities; using Parallel = HotChocolate.Fusion.Execution.Nodes.Parallel; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Planning.Pipeline; internal sealed class ExecutionTreeBuilderMiddleware : IQueryPlanMiddleware { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/FieldRequirementsPlannerMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/FieldRequirementsPlannerMiddleware.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/FieldRequirementsPlannerMiddleware.cs rename to src/HotChocolate/Fusion/src/Core/Planning/Pipeline/FieldRequirementsPlannerMiddleware.cs index 3a2aa9a69a1..55ac6f555b8 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/FieldRequirementsPlannerMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/FieldRequirementsPlannerMiddleware.cs @@ -1,11 +1,10 @@ -using System.Runtime.CompilerServices; using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Metadata; using HotChocolate.Fusion.Utilities; using HotChocolate.Utilities; using static System.StringComparer; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Planning.Pipeline; internal sealed class FieldRequirementsPlannerMiddleware : IQueryPlanMiddleware { diff --git a/src/HotChocolate/Fusion/src/Core/Planning/RequirementsPlannerMiddleware.cs b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/RequirementsPlannerMiddleware.cs similarity index 99% rename from src/HotChocolate/Fusion/src/Core/Planning/RequirementsPlannerMiddleware.cs rename to src/HotChocolate/Fusion/src/Core/Planning/Pipeline/RequirementsPlannerMiddleware.cs index f7d49a372ca..4695ec717db 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/RequirementsPlannerMiddleware.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/Pipeline/RequirementsPlannerMiddleware.cs @@ -2,7 +2,7 @@ using HotChocolate.Utilities; using static System.StringComparer; -namespace HotChocolate.Fusion.Planning; +namespace HotChocolate.Fusion.Planning.Pipeline; /// /// The requirements planer will analyze the requirements for each diff --git a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs index d1487388193..f0c97fdb6a3 100644 --- a/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs +++ b/src/HotChocolate/Fusion/src/Core/Planning/QueryPlanner.cs @@ -1,6 +1,7 @@ using HotChocolate.Execution.Processing; using HotChocolate.Fusion.Execution.Nodes; using HotChocolate.Fusion.Metadata; +using HotChocolate.Fusion.Planning.Pipeline; namespace HotChocolate.Fusion.Planning; From 4c7911f9cfa82d0e8cb3eb85bfd0be802ea6f8da Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 18:34:39 +0200 Subject: [PATCH 16/17] edits --- .../Processing/Result/ResultBuilder.cs | 12 ++++ .../src/Core/Execution/Nodes/QueryPlan.cs | 60 +++++++++++++------ .../src/Core/Execution/Nodes/Subscribe.cs | 4 +- .../src/Core/HotChocolate.Fusion.csproj | 1 + .../Fusion/src/Core/WellKnownContextData.cs | 7 ++- .../Fusion/test/Core.Tests/TestHelper.cs | 2 + ...nd_Reviews_And_Products_Introspection.snap | 5 ++ ...eviews_And_Products_Query_TopProducts.snap | 5 ++ ...d_Reviews_And_Products_Query_TypeName.snap | 5 ++ ...d_Reviews_And_Products_With_Variables.snap | 5 ++ ...ts.Authors_And_Reviews_Batch_Requests.snap | 5 ++ ...Authors_And_Reviews_Query_GetUserById.snap | 5 ++ ...ery_GetUserById_With_Invalid_Id_Value.snap | 5 ++ ...hors_And_Reviews_Query_GetUserReviews.snap | 5 ++ ..._And_Reviews_Query_Reformat_AuthorIds.snap | 5 ++ ...Authors_And_Reviews_Query_ReviewsUser.snap | 5 ++ ...ationTests.Fetch_User_With_Node_Field.snap | 5 ++ ...er_With_Node_Field_From_Two_Subgraphs.snap | 5 ++ ...ser_With_Node_Field_Pass_In_Review_Id.snap | 5 ++ ...er_With_Node_Field_Pass_In_Unknown_Id.snap | 5 ++ ...onTests.Forward_Nested_Node_Variables.snap | 5 ++ ...Tests.Forward_Nested_Object_Variables.snap | 5 ++ ...grationTests.Forward_Nested_Variables.snap | 5 ++ ...ionTests.GetFirstPage_With_After_Null.snap | 5 ++ ...egrationTests.Require_Data_In_Context.snap | 5 ++ ...rationTests.Require_Data_In_Context_2.snap | 5 ++ ...rationTests.Require_Data_In_Context_3.snap | 5 ++ ...tionTests.TypeName_Field_On_QueryRoot.snap | 5 ++ ...Tests.Accounts_Offline_Author_NonNull.snap | 5 ++ ...ests.Accounts_Offline_Author_Nullable.snap | 5 ++ ..._Offline_Reviews_ListElement_Nullable.snap | 5 ++ ..._And_Reviews_Subscription_OnNewReview.snap | 5 ++ .../FileUploadTests.UploadFile.snap | 5 ++ .../FileUploadTests.UploadFile_2.snap | 5 ++ .../InterfaceTests.Query_Interface_List.snap | 5 ++ ...ts.Query_Interface_List_With_Fragment.snap | 5 ++ ...ry_Interface_List_With_Fragment_Fetch.snap | 5 ++ ...ests.Error_Union_With_Inline_Fragment.snap | 5 ++ ..._With_Inline_Fragment_Errors_Not_Null.snap | 5 ++ .../UnionTests.Error_Union_With_TypeName.snap | 5 ++ ...r_Union_With_TypeName_Errors_Not_Null.snap | 5 ++ .../Skimmed/Serialization/SchemaFormatter.cs | 6 ++ 42 files changed, 247 insertions(+), 20 deletions(-) diff --git a/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs b/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs index 3dd59ef18d1..55ef58788ae 100644 --- a/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs +++ b/src/HotChocolate/Core/src/Execution/Processing/Result/ResultBuilder.cs @@ -137,6 +137,18 @@ public void RegisterForCleanup(T state, Func action) _cleanupTasks.Add(() => action(state)); } } + + public void RegisterForCleanup(T state) where T : IDisposable + { + lock (_cleanupTasks) + { + _cleanupTasks.Add(() => + { + state.Dispose(); + return default!; + }); + } + } public void SetPath(Path? path) => _path = path; diff --git a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs index 032742a9c42..d229ad364a7 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs @@ -1,5 +1,6 @@ using System.Buffers; using System.Runtime.CompilerServices; +using System.Security.Cryptography; using System.Text; using System.Text.Json; using HotChocolate.Execution; @@ -8,6 +9,8 @@ using HotChocolate.Fusion.Planning; using HotChocolate.Language; using HotChocolate.Language.Visitors; +using HotChocolate.Utilities; +using static HotChocolate.Fusion.FusionContextDataKeys; using static HotChocolate.Fusion.Utilities.Utf8QueryPlanPropertyNames; using ThrowHelper = HotChocolate.Fusion.Utilities.ThrowHelper; @@ -23,6 +26,7 @@ internal sealed class QueryPlan private readonly Dictionary<(ISelectionSet, string), string[]> _exportPathsLookup = new(); private readonly (string Key, string DisplayName)[] _exportKeyToVariableName; private readonly IReadOnlySet _selectionSets; + private string? _hash; /// /// Initializes a new instance of . @@ -84,6 +88,22 @@ public QueryPlan( } } + public string Hash + { + get + { + if (_hash is not null) + { + return _hash; + } + + using var bufferWriter = new ArrayWriter(); + Format(bufferWriter); + _hash = ComputeHash(bufferWriter.GetSpan()); + return _hash; + } + } + /// /// Gets the root node of the query plan. /// @@ -149,13 +169,15 @@ public async Task ExecuteAsync( { var bufferWriter = new ArrayBufferWriter(); context.QueryPlan.Format(bufferWriter); - operationContext.Result.SetExtension( - "queryPlan", - new RawJsonValue(bufferWriter.WrittenMemory)); + + var memory = bufferWriter.WrittenMemory; + _hash ??= ComputeHash(memory.Span); + operationContext.Result.SetExtension(QueryPlanProp, new RawJsonValue(memory)); + operationContext.Result.SetExtension(QueryPlanHashProp, _hash); } // we store the context on the result for unit tests. - operationContext.Result.SetContextData("queryPlan", context.QueryPlan); + operationContext.Result.SetContextData(QueryPlanProp, context.QueryPlan); // Enqueue root node to initiate the execution process. var rootSelectionSet = Unsafe.As(context.Operation.RootSelectionSet); @@ -196,12 +218,7 @@ public async Task ExecuteAsync( } } - context.Result.RegisterForCleanup( - () => - { - context.Dispose(); - return default; - }); + context.Result.RegisterForCleanup(context); return context.Result.BuildResult(); } @@ -240,12 +257,7 @@ public Task SubscribeAsync( () => subscriptionNode.SubscribeAsync(context, cancellationToken), kind: ExecutionResultKind.SubscriptionResult); - result.RegisterForCleanup( - () => - { - context.Dispose(); - return default; - }); + result.RegisterForCleanup(context); return Task.FromResult(result); } @@ -261,7 +273,6 @@ public void Format(IBufferWriter writer) public void Format(Utf8JsonWriter writer) { writer.WriteStartObject(); - writer.WriteString(DocumentProp, _operation.Document.ToString(false)); if (!string.IsNullOrEmpty(_operation.Name)) @@ -304,6 +315,21 @@ public override string ToString() return Encoding.UTF8.GetString(bufferWriter.WrittenSpan); } + private static unsafe string ComputeHash(ReadOnlySpan document) + { + Span hash = stackalloc byte[SHA1.HashSizeInBytes]; + ComputeHash(ref hash, document); + return Convert.ToHexString(hash); + } + + private static void ComputeHash(ref Span hash, ReadOnlySpan document) + { + if (SHA1.TryHashData(document, hash, out var bytesWritten)) + { + hash = hash[..bytesWritten]; + } + } + private sealed class ExportPathVisitor : SyntaxWalker { protected override ISyntaxVisitorAction Enter( diff --git a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Subscribe.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Subscribe.cs index e7d7a1d7e97..b8a4da9f9b6 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Subscribe.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/Subscribe.cs @@ -76,13 +76,13 @@ internal async IAsyncEnumerable SubscribeAsync( var bufferWriter = new ArrayBufferWriter(); context.QueryPlan.Format(bufferWriter); operationContext.Result.SetExtension( - FusionContextDataKeys.QueryPlan, + FusionContextDataKeys.QueryPlanProp, new RawJsonValue(bufferWriter.WrittenMemory)); } // We store the query plan on the result for unit tests and other inspection. operationContext.Result.SetContextData( - FusionContextDataKeys.QueryPlan, + FusionContextDataKeys.QueryPlanProp, context.QueryPlan); } initialResponse = false; diff --git a/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj b/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj index e7f6eede766..c045e09a7a0 100644 --- a/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj +++ b/src/HotChocolate/Fusion/src/Core/HotChocolate.Fusion.csproj @@ -5,6 +5,7 @@ HotChocolate.Fusion enable enable + true $(WarningsAsErrors);nullable diff --git a/src/HotChocolate/Fusion/src/Core/WellKnownContextData.cs b/src/HotChocolate/Fusion/src/Core/WellKnownContextData.cs index 57c1b5f7708..19db33adb74 100644 --- a/src/HotChocolate/Fusion/src/Core/WellKnownContextData.cs +++ b/src/HotChocolate/Fusion/src/Core/WellKnownContextData.cs @@ -8,5 +8,10 @@ internal static class FusionContextDataKeys /// /// The response state key that is used to store the query plan. /// - public const string QueryPlan = "queryPlan"; + public const string QueryPlanProp = "queryPlan"; + + /// + /// The response state key that is used to store the query plan hash. + /// + public const string QueryPlanHashProp = "queryPlanHash"; } diff --git a/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs b/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs index 23a8236b4e4..f385b7aa294 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs +++ b/src/HotChocolate/Fusion/test/Core.Tests/TestHelper.cs @@ -22,6 +22,7 @@ public static void CollectSnapshotData( value is QueryPlan queryPlan) { snapshot.Add(queryPlan, "QueryPlan"); + snapshot.Add(queryPlan.Hash, "QueryPlan Hash"); } snapshot.Add(result, "Result"); @@ -46,6 +47,7 @@ public static async Task CollectStreamSnapshotData( value is QueryPlan queryPlan) { snapshot.Add(queryPlan, "QueryPlan"); + snapshot.Add(queryPlan.Hash, "QueryPlan Hash"); } snapshot.Add(item, $"Result {++i}"); diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap index a0241ff5560..4acec18250b 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap @@ -40,6 +40,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +55A6EAC2482A480497182BB2805B0DD94B672913 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap index 13fcb3e3cc0..e53e58c1ad7 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap @@ -69,6 +69,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +1CE1EAAA04AEEE1816BEF46859D74025D809D3E6 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap index e07326ac140..1b625982a8d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap @@ -79,6 +79,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap index 02157979b6d..52829d62a82 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap @@ -37,6 +37,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +880C4AA1AC79FA98902A3DF38D06B802BCB6D03F +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap index a653892f3d8..df175b24ac9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap @@ -66,6 +66,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +218F499120A5E77675E61177E4B7644536D845CE +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap index 95c8fea94d0..6e9626b5c71 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap @@ -32,6 +32,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +CB1F74F4EBD72A2E87CA3DC978C149C83A76363B +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap index 9fa97dbf20a..a85d3ddc78c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap @@ -32,6 +32,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap index 6616234a149..d1dd73bf7ef 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap @@ -69,6 +69,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +6B0B3A9C34510D81F337DFE0C0CA3EE0C6539EFE +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap index 7a029ffb810..162e4c52ffe 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap @@ -34,6 +34,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap index 1a6c900c3e9..43b41b42d6d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap @@ -92,6 +92,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +1CB64DDD3CB9123EC0DEE36279D98749B97168F1 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap index e4a90c05167..661c35d2f4e 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap @@ -77,6 +77,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap index c9544d9be1d..fe030a580f4 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap @@ -106,6 +106,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap index 69448c533a0..1c5b03aa7fc 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap @@ -77,6 +77,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap index 9c3aa7e0a50..6965a31fd06 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap @@ -77,6 +77,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +3DB2B676F51CCAF72132F9FA6A5BFFC74A8673CB +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap index bbd6da7331c..818008de412 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap @@ -81,6 +81,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap index efd950e1016..661964ccf48 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap @@ -45,6 +45,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap index 90e10a34135..2498ac2a0cc 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap @@ -41,6 +41,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +AA901187C7ECA34C1FFBACF7003CA2F1D72A5C5F +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap index 865d172c0b0..5415e459819 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap @@ -39,6 +39,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap index 247873182f5..7ffdabc4b74 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap @@ -142,6 +142,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap index 829ada21bf0..8231677782b 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap @@ -141,6 +141,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap index dde568e6167..e6d44c83f3d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap @@ -176,6 +176,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5041EDD8D59F743929E6091E7D3DCD41F8BF1C16 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap index 3efc14160be..1e014b672f2 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap @@ -28,6 +28,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +284455BDEECD2B07089D863471614CE2E4F6DD31 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap index 77b3c19bff2..38ddd303a74 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap @@ -66,6 +66,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +4A392602C86159D605805EE31455823E60B4EC1F +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap index 97d9ed4ccc5..b737a4e4666 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap @@ -66,6 +66,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap index eb8cfe347d9..34f290674e9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap @@ -66,6 +66,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap index bb95c319d19..be8bd72b8f7 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap @@ -37,6 +37,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +427382C38EF53BB77C0EF8B76E8710D49AD107BF +--------------- + Result 1 --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap index 19e1f543bb2..ebbc5a9b04d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap @@ -37,6 +37,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap index e17363093d9..c8b72f9024c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap @@ -37,6 +37,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap index 90eefcbc742..333f681faa7 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap @@ -36,6 +36,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +3E7972FDD6F7E2840957BF58FB5514E1640700AC +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap index f2ca5f3bc7c..aeb9b2555d0 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap @@ -70,6 +70,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +AC7277F57F8F3BB45E913EF529B2C978E34A92DA +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap index f2ca5f3bc7c..09c215c570b 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap @@ -70,6 +70,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap index b56d76dea82..c10b3455561 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap @@ -43,6 +43,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +614144BE8D16C4C78D3FA4198AA577C33B74C43F +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap index e2cdfb7befe..00e0118768a 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap @@ -43,6 +43,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap index 22f8446bcb9..2cf1917185d 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap @@ -40,6 +40,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +23A077152477BED4597B6351F30E28AE7AEA4C1A +--------------- + Result --------------- { diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap index f2a562b02a2..e69e1437a36 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap @@ -40,6 +40,11 @@ QueryPlan } --------------- +QueryPlan Hash +--------------- +8D3EB2F4F921592A08D6B7DD33F40F563D33F066 +--------------- + Result --------------- { diff --git a/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs b/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs index e8398b8fab0..65bbefa2ba7 100644 --- a/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs +++ b/src/HotChocolate/Skimmed/src/Skimmed/Serialization/SchemaFormatter.cs @@ -17,6 +17,12 @@ public static string FormatAsString(Schema schema, bool indented = true) { var context = new VisitorContext(); _visitor.VisitSchema(schema, context); + + if (!indented) + { + ((DocumentNode) context.Result!).ToString(false); + } + return ((DocumentNode)context.Result!).ToString(_options); } From bf880af8f4b11dd60a54efe478ea9cb4003e8442 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Sat, 22 Jul 2023 18:53:36 +0200 Subject: [PATCH 17/17] edits --- .../src/Core/Execution/Nodes/QueryPlan.cs | 19 +++++++++---------- ...nd_Reviews_And_Products_Introspection.snap | 2 +- ...eviews_And_Products_Query_TopProducts.snap | 2 +- ...d_Reviews_And_Products_Query_TypeName.snap | 2 +- ...d_Reviews_And_Products_With_Variables.snap | 2 +- ...ts.Authors_And_Reviews_Batch_Requests.snap | 2 +- ...Authors_And_Reviews_Query_GetUserById.snap | 2 +- ...ery_GetUserById_With_Invalid_Id_Value.snap | 2 +- ...hors_And_Reviews_Query_GetUserReviews.snap | 2 +- ..._And_Reviews_Query_Reformat_AuthorIds.snap | 2 +- ...Authors_And_Reviews_Query_ReviewsUser.snap | 2 +- ...ationTests.Fetch_User_With_Node_Field.snap | 2 +- ...er_With_Node_Field_From_Two_Subgraphs.snap | 2 +- ...ser_With_Node_Field_Pass_In_Review_Id.snap | 2 +- ...er_With_Node_Field_Pass_In_Unknown_Id.snap | 2 +- ...onTests.Forward_Nested_Node_Variables.snap | 2 +- ...Tests.Forward_Nested_Object_Variables.snap | 2 +- ...grationTests.Forward_Nested_Variables.snap | 2 +- ...ionTests.GetFirstPage_With_After_Null.snap | 2 +- ...egrationTests.Require_Data_In_Context.snap | 2 +- ...rationTests.Require_Data_In_Context_2.snap | 2 +- ...rationTests.Require_Data_In_Context_3.snap | 2 +- ...tionTests.TypeName_Field_On_QueryRoot.snap | 2 +- ...Tests.Accounts_Offline_Author_NonNull.snap | 2 +- ...ests.Accounts_Offline_Author_Nullable.snap | 2 +- ..._Offline_Reviews_ListElement_Nullable.snap | 2 +- ..._And_Reviews_Subscription_OnNewReview.snap | 2 +- .../FileUploadTests.UploadFile.snap | 2 +- .../FileUploadTests.UploadFile_2.snap | 2 +- .../InterfaceTests.Query_Interface_List.snap | 2 +- ...ts.Query_Interface_List_With_Fragment.snap | 2 +- ...ry_Interface_List_With_Fragment_Fetch.snap | 2 +- ...ests.Error_Union_With_Inline_Fragment.snap | 2 +- ..._With_Inline_Fragment_Errors_Not_Null.snap | 2 +- .../UnionTests.Error_Union_With_TypeName.snap | 2 +- ...r_Union_With_TypeName_Errors_Not_Null.snap | 2 +- 36 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs index d229ad364a7..77974919635 100644 --- a/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs +++ b/src/HotChocolate/Fusion/src/Core/Execution/Nodes/QueryPlan.cs @@ -21,6 +21,7 @@ namespace HotChocolate.Fusion.Execution.Nodes; /// internal sealed class QueryPlan { + private static readonly JsonWriterOptions _jsonOptions = new() { Indented = true }; private readonly IOperation _operation; private readonly Dictionary _exportKeysLookup = new(); private readonly Dictionary<(ISelectionSet, string), string[]> _exportPathsLookup = new(); @@ -53,7 +54,7 @@ public QueryPlan( { throw new ArgumentNullException(nameof(exports)); } - + _operation = operation ?? throw new ArgumentNullException(nameof(operation)); RootNode = rootNode ?? throw new ArgumentNullException(nameof(rootNode)); _selectionSets = selectionSets ?? throw new ArgumentNullException(nameof(selectionSets)); @@ -99,7 +100,7 @@ public string Hash using var bufferWriter = new ArrayWriter(); Format(bufferWriter); - _hash = ComputeHash(bufferWriter.GetSpan()); + _hash = ComputeHash(bufferWriter.GetWrittenSpan()); return _hash; } } @@ -122,7 +123,7 @@ public string Hash /// public bool HasNodesFor(ISelectionSet selectionSet) => _selectionSets.Contains(selectionSet); - + public IReadOnlyList GetExportKeys(ISelectionSet selectionSet) => _exportKeysLookup.TryGetValue(selectionSet, out var keys) ? keys @@ -264,8 +265,7 @@ public Task SubscribeAsync( public void Format(IBufferWriter writer) { - var jsonOptions = new JsonWriterOptions { Indented = true }; - using var jsonWriter = new Utf8JsonWriter(writer, jsonOptions); + using var jsonWriter = new Utf8JsonWriter(writer, _jsonOptions); Format(jsonWriter); jsonWriter.Flush(); } @@ -296,7 +296,7 @@ public void Format(Utf8JsonWriter writer) writer.WriteString(NameProp, displayName); writer.WriteEndObject(); } - + writer.WriteEndArray(); } @@ -306,8 +306,7 @@ public void Format(Utf8JsonWriter writer) public override string ToString() { var bufferWriter = new ArrayBufferWriter(); - var jsonOptions = new JsonWriterOptions { Indented = true }; - using var jsonWriter = new Utf8JsonWriter(bufferWriter, jsonOptions); + using var jsonWriter = new Utf8JsonWriter(bufferWriter, _jsonOptions); Format(jsonWriter); jsonWriter.Flush(); @@ -320,8 +319,8 @@ private static unsafe string ComputeHash(ReadOnlySpan document) Span hash = stackalloc byte[SHA1.HashSizeInBytes]; ComputeHash(ref hash, document); return Convert.ToHexString(hash); - } - + } + private static void ComputeHash(ref Span hash, ReadOnlySpan document) { if (SHA1.TryHashData(document, hash, out var bytesWritten)) diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap index 4acec18250b..12fca7877d3 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Introspection.snap @@ -42,7 +42,7 @@ QueryPlan QueryPlan Hash --------------- -55A6EAC2482A480497182BB2805B0DD94B672913 +3F4377696891DA698EAFD7B8D8BD8CB60FEC342E --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap index e53e58c1ad7..a88b67ea2e3 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TopProducts.snap @@ -71,7 +71,7 @@ QueryPlan QueryPlan Hash --------------- -1CE1EAAA04AEEE1816BEF46859D74025D809D3E6 +9CF1B1E2CA1A4C1F4E9FC40EC599B21F31DB2437 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap index 1b625982a8d..37aa85b8d51 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_Query_TypeName.snap @@ -81,7 +81,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +E4B2B0C3E838D31C20FF059EF4CBACA3E72DE42B --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap index 52829d62a82..731d8a7718b 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_And_Products_With_Variables.snap @@ -39,7 +39,7 @@ QueryPlan QueryPlan Hash --------------- -880C4AA1AC79FA98902A3DF38D06B802BCB6D03F +D95EB3DB7C743969F7A95EBD409217BF5E1BB5D8 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap index df175b24ac9..3f6e427fdee 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Batch_Requests.snap @@ -68,7 +68,7 @@ QueryPlan QueryPlan Hash --------------- -218F499120A5E77675E61177E4B7644536D845CE +39C1F28BDCF0C9E19BD6B0A1B1BEF9F4E5039F2C --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap index 6e9626b5c71..283a5059bd9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById.snap @@ -34,7 +34,7 @@ QueryPlan QueryPlan Hash --------------- -CB1F74F4EBD72A2E87CA3DC978C149C83A76363B +09961F039AB8E9A5FDD54304FF938C9277EF0562 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap index a85d3ddc78c..fb88740d6d2 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserById_With_Invalid_Id_Value.snap @@ -34,7 +34,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +7D1C123A297876C8F5C32BC231900D1706858A87 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap index d1dd73bf7ef..beb638f2fb0 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_GetUserReviews.snap @@ -71,7 +71,7 @@ QueryPlan QueryPlan Hash --------------- -6B0B3A9C34510D81F337DFE0C0CA3EE0C6539EFE +685DB664FE69542B88C2615B00C185EF96287433 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap index 162e4c52ffe..d3ba0f2afbe 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_Reformat_AuthorIds.snap @@ -36,7 +36,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +9F1489CA5289059663ED412471F2C4B87F8A4911 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap index 43b41b42d6d..b39772dc3de 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Authors_And_Reviews_Query_ReviewsUser.snap @@ -94,7 +94,7 @@ QueryPlan QueryPlan Hash --------------- -1CB64DDD3CB9123EC0DEE36279D98749B97168F1 +0063E44988E01990A3C87BFCB7119F223B2801A5 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap index 661c35d2f4e..323ea52e107 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field.snap @@ -79,7 +79,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +1A21CA422439C6540C53FC5028089D965C5F8A03 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap index fe030a580f4..9b0aabce59c 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_From_Two_Subgraphs.snap @@ -108,7 +108,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +CCEE98D282F5BD134056BA408A6E361770DC6545 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap index 1c5b03aa7fc..5469e028850 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Review_Id.snap @@ -79,7 +79,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +1A21CA422439C6540C53FC5028089D965C5F8A03 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap index 6965a31fd06..3621d9c01ce 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Fetch_User_With_Node_Field_Pass_In_Unknown_Id.snap @@ -79,7 +79,7 @@ QueryPlan QueryPlan Hash --------------- -3DB2B676F51CCAF72132F9FA6A5BFFC74A8673CB +1A21CA422439C6540C53FC5028089D965C5F8A03 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap index 818008de412..f89f7105a1e 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Node_Variables.snap @@ -83,7 +83,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +802664ED0C849F707F3AA4098DE07E5D1D9E80DB --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap index 661964ccf48..7fac168f60f 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Object_Variables.snap @@ -47,7 +47,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +8ECD591E2162E9499A4E7DAC6CA05988445547E6 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap index 2498ac2a0cc..d3288f7c013 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Forward_Nested_Variables.snap @@ -43,7 +43,7 @@ QueryPlan QueryPlan Hash --------------- -AA901187C7ECA34C1FFBACF7003CA2F1D72A5C5F +CAA1FE80B0D6C630C75664DB34FD91624B849F27 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap index 5415e459819..63d8b40659a 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.GetFirstPage_With_After_Null.snap @@ -41,7 +41,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +6FAD9C915B229E9D33AB4A980BEB7351BAD35924 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap index 7ffdabc4b74..38efdfc9215 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context.snap @@ -144,7 +144,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +FA17FCF617B8DC60AF20B5A25813C8D10A148E63 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap index 8231677782b..1a35ac41728 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_2.snap @@ -143,7 +143,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +BB5F403C581EDD0F0BF7D150A31CD258B23A6C6B --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap index e6d44c83f3d..51e87411dd9 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.Require_Data_In_Context_3.snap @@ -178,7 +178,7 @@ QueryPlan QueryPlan Hash --------------- -5041EDD8D59F743929E6091E7D3DCD41F8BF1C16 +5C57D69756182D7C8B6A6610E6082C0C5E5A63BD --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap index 1e014b672f2..d0704d8fe9a 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/DemoIntegrationTests.TypeName_Field_On_QueryRoot.snap @@ -30,7 +30,7 @@ QueryPlan QueryPlan Hash --------------- -284455BDEECD2B07089D863471614CE2E4F6DD31 +697698C162C0AB8A3054708CABD070BFABE80B8B --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap index 38ddd303a74..256563ccd76 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_NonNull.snap @@ -68,7 +68,7 @@ QueryPlan QueryPlan Hash --------------- -4A392602C86159D605805EE31455823E60B4EC1F +E66032C9090CEF0A5BAA67C81A653C72E1C5DF85 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap index b737a4e4666..256783949b7 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Author_Nullable.snap @@ -68,7 +68,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +A66357625887EC4026675084B4B19B69ED1032E2 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap index 34f290674e9..a8025788c4b 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/ErrorTests.Accounts_Offline_Reviews_ListElement_Nullable.snap @@ -68,7 +68,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +BB99901FC94CC98D06A39A0DFD9055904F11F280 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap index be8bd72b8f7..43e469a083f 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/EventStreamTests.Authors_And_Reviews_Subscription_OnNewReview.snap @@ -39,7 +39,7 @@ QueryPlan QueryPlan Hash --------------- -427382C38EF53BB77C0EF8B76E8710D49AD107BF +F823835BFACD5B49C03063C112F1293EAB40DE1E --------------- Result 1 diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap index ebbc5a9b04d..6d919199250 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile.snap @@ -39,7 +39,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +C3298260FD8612E0FE8DB108E15FB4122CBBF47C --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap index c8b72f9024c..751d5c54cf8 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/FileUploadTests.UploadFile_2.snap @@ -39,7 +39,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +D968748DEC5B900198E5ABEBE187BCF83431A5AC --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap index 333f681faa7..ac824f9704b 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List.snap @@ -38,7 +38,7 @@ QueryPlan QueryPlan Hash --------------- -3E7972FDD6F7E2840957BF58FB5514E1640700AC +3DE1889AD56C0846C24B425F1BC050FD67F7A74B --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap index aeb9b2555d0..ca93fb27af1 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment.snap @@ -72,7 +72,7 @@ QueryPlan QueryPlan Hash --------------- -AC7277F57F8F3BB45E913EF529B2C978E34A92DA +A805DF9A4E82B987E447CD2E2F735DDB9DFBCFBD --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap index 09c215c570b..ca93fb27af1 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/InterfaceTests.Query_Interface_List_With_Fragment_Fetch.snap @@ -72,7 +72,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +A805DF9A4E82B987E447CD2E2F735DDB9DFBCFBD --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap index c10b3455561..bf16153b9ac 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment.snap @@ -45,7 +45,7 @@ QueryPlan QueryPlan Hash --------------- -614144BE8D16C4C78D3FA4198AA577C33B74C43F +62AB3FC1A9F040C10377EAF01865D8D8CB406CB4 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap index 00e0118768a..a367a30bf74 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_Inline_Fragment_Errors_Not_Null.snap @@ -45,7 +45,7 @@ QueryPlan QueryPlan Hash --------------- -5C3EB80066420002BC3DCC7CA4AB6EFAD7ED4AE5 +62AB3FC1A9F040C10377EAF01865D8D8CB406CB4 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap index 2cf1917185d..5628f297f26 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName.snap @@ -42,7 +42,7 @@ QueryPlan QueryPlan Hash --------------- -23A077152477BED4597B6351F30E28AE7AEA4C1A +56E8F115508796D7CB6FCA52CE2AFFCF458ED8E0 --------------- Result diff --git a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap index e69e1437a36..d8782d55a44 100644 --- a/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap +++ b/src/HotChocolate/Fusion/test/Core.Tests/__snapshots__/UnionTests.Error_Union_With_TypeName_Errors_Not_Null.snap @@ -42,7 +42,7 @@ QueryPlan QueryPlan Hash --------------- -8D3EB2F4F921592A08D6B7DD33F40F563D33F066 +56E8F115508796D7CB6FCA52CE2AFFCF458ED8E0 --------------- Result