Skip to content

Commit 9af30cc

Browse files
authored
[Fusion] Fixed reindex selection set after merging requirements. (#8505)
1 parent 834a97c commit 9af30cc

File tree

8 files changed

+419
-70
lines changed

8 files changed

+419
-70
lines changed

src/HotChocolate/AspNetCore/src/AspNetCore/Extensions/HotChocolateAspNetCoreServiceCollectionExtensions.Warmup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public static partial class HotChocolateAspNetCoreServiceCollectionExtensions
2626
/// </exception>
2727
public static IRequestExecutorBuilder InitializeOnStartup(
2828
this IRequestExecutorBuilder builder,
29+
2930
Func<IRequestExecutor, CancellationToken, Task>? warmup = null,
3031
bool keepWarm = false)
3132
{

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/OperationPlanner.cs

Lines changed: 64 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ node with
9696
InternalOperationDefinition = operationDefinition,
9797
ShortHash = shortHash,
9898
SchemaName = "None",
99-
SelectionSetIndex = index.ToImmutable(),
99+
SelectionSetIndex = index,
100100
Backlog = ImmutableStack<WorkItem>.Empty.Push(workItem),
101101
PathCost = 1,
102102
BacklogCost = 1
@@ -149,15 +149,13 @@ node with
149149
backlog = backlog.Push(OperationWorkItem.CreateRoot(selectionSet));
150150
}
151151

152-
index = indexBuilder.ToImmutable();
153-
154152
var node = new PlanNode
155153
{
156154
OperationDefinition = operationDefinition,
157155
InternalOperationDefinition = operationDefinition,
158156
ShortHash = shortHash,
159157
SchemaName = ISchemaDefinition.DefaultName,
160-
SelectionSetIndex = index,
158+
SelectionSetIndex = indexBuilder,
161159
Backlog = backlog,
162160
PathCost = 1,
163161
BacklogCost = 1
@@ -321,7 +319,7 @@ lookup is null
321319
InternalOperationDefinition = current.InternalOperationDefinition,
322320
ShortHash = current.ShortHash,
323321
SchemaName = current.SchemaName,
324-
SelectionSetIndex = index.ToImmutable(),
322+
SelectionSetIndex = index,
325323
Backlog = backlog,
326324
Steps = current.Steps.Add(step),
327325
PathCost = current.PathCost,
@@ -375,14 +373,18 @@ private PlanNode InlineLookupRequirements(
375373
InlineSelections(
376374
step.Definition,
377375
index,
378-
step.Type,
376+
workItemSelectionSet.Type,
379377
index.GetId(resolvable),
380378
resolvable);
381379

382380
var updatedStep = step with
383381
{
384382
Definition = operation,
385383

384+
// we need to update the selection sets that this plan step
385+
// has as the requirement could have introduced new ones.
386+
SelectionSets = SelectionSetIndexer.CreateIdSet(operation.SelectionSet, index),
387+
386388
// we add the new lookup node to the dependents of the current step.
387389
// the new lookup node will be the next index added which is the last index aka Count.
388390
Dependents = step.Dependents.Add(lookupStepId)
@@ -524,7 +526,7 @@ private void PlanInlineFieldWithRequirements(
524526
InternalOperationDefinition = current.InternalOperationDefinition,
525527
ShortHash = current.ShortHash,
526528
SchemaName = current.SchemaName,
527-
SelectionSetIndex = index.ToImmutable(),
529+
SelectionSetIndex = index,
528530
Backlog = backlog,
529531
Steps = steps,
530532
PathCost = current.PathCost,
@@ -686,7 +688,7 @@ private void PlanFieldWithRequirement(
686688
InternalOperationDefinition = current.InternalOperationDefinition,
687689
ShortHash = current.ShortHash,
688690
SchemaName = current.SchemaName,
689-
SelectionSetIndex = index.ToImmutable(),
691+
SelectionSetIndex = index,
690692
Backlog = backlog,
691693
Steps = steps.Add(step),
692694
PathCost = current.PathCost,
@@ -794,6 +796,15 @@ private void PlanFieldWithRequirement(
794796
continue;
795797
}
796798

799+
// the resolvable part of the requirement could be different from the requirement
800+
// if we are unable to inline the complete requirement into a single plan step.
801+
// in this case we will register the resolvable part as part of the requirements selection set
802+
// so that they logically belong together.
803+
if (resolvable != requirements)
804+
{
805+
index.Register(workItem.Selection.SelectionSetId, resolvable);
806+
}
807+
797808
var operation =
798809
InlineSelections(
799810
step.Definition,
@@ -858,55 +869,61 @@ private OperationDefinitionNode InlineSelections(
858869
var rewriter = SyntaxRewriter.Create<Stack<ISyntaxNode>>(
859870
(node, path) =>
860871
{
861-
if (node is SelectionSetNode selectionSet)
872+
if (node is not SelectionSetNode selectionSet)
862873
{
863-
var originalSelectionSet = (SelectionSetNode)path.Peek();
864-
var id = index.GetId(originalSelectionSet);
874+
return node;
875+
}
865876

866-
if (!ReferenceEquals(originalSelectionSet, selectionSet))
867-
{
868-
index.Register(originalSelectionSet, selectionSet);
869-
}
877+
var originalSelectionSet = (SelectionSetNode)path.Peek();
878+
var id = index.GetId(originalSelectionSet);
870879

871-
if (targetSelectionSetId == id)
880+
if (!ReferenceEquals(originalSelectionSet, selectionSet))
881+
{
882+
index.Register(originalSelectionSet, selectionSet);
883+
}
884+
885+
if (targetSelectionSetId != id)
886+
{
887+
return node;
888+
}
889+
890+
SelectionSetNode newSelectionSet;
891+
892+
if (inlineInternal)
893+
{
894+
var size = selectionSet.Selections.Count + selectionsToInline.Selections.Count;
895+
var selections = new List<ISelectionNode>(size);
896+
selections.AddRange(originalSelectionSet.Selections);
897+
898+
foreach (var selection in selectionsToInline.Selections)
872899
{
873-
SelectionSetNode newSelectionSet;
900+
var directives = AddInternalDirective(selection);
874901

875-
if (inlineInternal)
902+
switch (selection)
876903
{
877-
var size = selectionSet.Selections.Count + selectionsToInline.Selections.Count;
878-
var selections = new List<ISelectionNode>(size);
879-
selections.AddRange(originalSelectionSet.Selections);
880-
881-
foreach (var selection in selectionsToInline.Selections)
882-
{
883-
var directives = AddInternalDirective(selection);
884-
885-
switch (selection)
886-
{
887-
case FieldNode field:
888-
selections.Add(field.WithDirectives(directives));
889-
break;
890-
891-
case InlineFragmentNode inlineFragment:
892-
selections.Add(inlineFragment.WithDirectives(directives));
893-
break;
894-
}
895-
}
896-
897-
newSelectionSet = new SelectionSetNode(selections);
898-
}
899-
else
900-
{
901-
newSelectionSet = _mergeRewriter.Merge(selectionSet, selectionsToInline, selectionSetType);
902-
}
904+
case FieldNode field:
905+
selections.Add(field.WithDirectives(directives));
906+
break;
903907

904-
index.Register(originalSelectionSet, newSelectionSet);
905-
return newSelectionSet;
908+
case InlineFragmentNode inlineFragment:
909+
selections.Add(inlineFragment.WithDirectives(directives));
910+
break;
911+
}
906912
}
913+
914+
newSelectionSet = new SelectionSetNode(selections);
915+
}
916+
else
917+
{
918+
newSelectionSet = _mergeRewriter.Merge(
919+
selectionSet,
920+
selectionsToInline,
921+
selectionSetType,
922+
index);
907923
}
908924

909-
return node;
925+
index.Register(originalSelectionSet, newSelectionSet);
926+
return newSelectionSet;
910927
},
911928
(node, path) =>
912929
{
@@ -1004,16 +1021,6 @@ public static ImmutableStack<WorkItem> Push(
10041021
return backlog;
10051022
}
10061023

1007-
public static ISelectionSetIndex ToImmutable(this ISelectionSetIndex index)
1008-
{
1009-
if (index is SelectionSetIndexBuilder builder)
1010-
{
1011-
return builder.Build();
1012-
}
1013-
1014-
return index;
1015-
}
1016-
10171024
public static void Enqueue(
10181025
this PriorityQueue<PlanNode, double> possiblePlans,
10191026
PlanNode planNodeTemplate,

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/PlanNode.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,21 @@ public sealed record PlanNode
3939
/// <summary>
4040
/// The index of the selection set.
4141
/// </summary>
42-
public required ISelectionSetIndex SelectionSetIndex { get; init; }
42+
public required ISelectionSetIndex SelectionSetIndex
43+
{
44+
get;
45+
init
46+
{
47+
if (value is SelectionSetIndexBuilder builder)
48+
{
49+
field = builder.Build();
50+
}
51+
else
52+
{
53+
field = value;
54+
}
55+
}
56+
}
4357

4458
public required ImmutableStack<WorkItem> Backlog { get; init; }
4559

0 commit comments

Comments
 (0)