Skip to content

Commit 0276674

Browse files
Add basic plan serialization (#7785)
1 parent 8b12f30 commit 0276674

File tree

10 files changed

+176
-103
lines changed

10 files changed

+176
-103
lines changed

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/Nodes/IOperationPlanNodeProvider.cs

Lines changed: 0 additions & 6 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace HotChocolate.Fusion.Planning.Nodes;
2+
3+
public interface IPlanNodeProvider
4+
{
5+
public IReadOnlyList<PlanNode> Nodes { get; }
6+
7+
public void AddChildNode(PlanNode node);
8+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using System.Text.Json;
2+
3+
namespace HotChocolate.Fusion.Planning;
4+
5+
public interface ISerializablePlanNode
6+
{
7+
PlanNodeKind Kind { get; }
8+
9+
void Serialize(Utf8JsonWriter writer);
10+
}

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Planning/Nodes/OperationPlanNode.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Text.Json;
12
using HotChocolate.Fusion.Types;
23
using HotChocolate.Language;
34

@@ -6,11 +7,11 @@ namespace HotChocolate.Fusion.Planning.Nodes;
67
/// <summary>
78
/// Represents an operation to resolve data from a specific source schema.
89
/// </summary>
9-
public sealed class OperationPlanNode : SelectionPlanNode, IOperationPlanNodeProvider
10+
public sealed class OperationPlanNode : SelectionPlanNode, IPlanNodeProvider, ISerializablePlanNode
1011
{
1112
private static readonly IReadOnlyDictionary<string, VariableDefinitionNode> _emptyVariableMap =
1213
new Dictionary<string, VariableDefinitionNode>();
13-
private List<OperationPlanNode>? _operations;
14+
private readonly List<PlanNode> _nodes = [];
1415
private Dictionary<string, VariableDefinitionNode>? _variables;
1516

1617
public OperationPlanNode(
@@ -43,20 +44,19 @@ public OperationPlanNode(
4344
public IReadOnlyDictionary<string, VariableDefinitionNode> VariableDefinitions
4445
=> _variables ?? _emptyVariableMap;
4546

46-
public IReadOnlyList<OperationPlanNode> Operations
47-
=> _operations ?? (IReadOnlyList<OperationPlanNode>)Array.Empty<OperationPlanNode>();
47+
public IReadOnlyList<PlanNode> Nodes => _nodes;
4848

4949
public void AddVariableDefinition(VariableDefinitionNode variable)
5050
{
5151
ArgumentNullException.ThrowIfNull(variable);
5252
(_variables ??= new Dictionary<string, VariableDefinitionNode>()).Add(variable.Variable.Name.Value, variable);
5353
}
5454

55-
public void AddOperation(OperationPlanNode operation)
55+
public void AddChildNode(PlanNode node)
5656
{
57-
ArgumentNullException.ThrowIfNull(operation);
58-
(_operations ??= []).Add(operation);
59-
operation.Parent = this;
57+
ArgumentNullException.ThrowIfNull(node);
58+
_nodes.Add(node);
59+
node.Parent = this;
6060
}
6161

6262
public OperationDefinitionNode ToSyntaxNode()
@@ -69,4 +69,16 @@ public OperationDefinitionNode ToSyntaxNode()
6969
Directives.ToSyntaxNode(),
7070
Selections.ToSyntaxNode());
7171
}
72+
73+
public PlanNodeKind Kind => PlanNodeKind.Operation;
74+
75+
public void Serialize(Utf8JsonWriter writer)
76+
{
77+
writer.WriteStartObject();
78+
SerializationHelper.WriteKind(writer, this);
79+
writer.WriteString("schema", SchemaName);
80+
writer.WriteString("document", ToSyntaxNode().ToString(indented: false));
81+
SerializationHelper.WriteChildNodes(writer, this);
82+
writer.WriteEndObject();
83+
}
7284
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace HotChocolate.Fusion.Planning;
2+
3+
public enum PlanNodeKind
4+
{
5+
Root,
6+
Operation
7+
}
Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,44 @@
1-
using System.Collections.Immutable;
2-
using HotChocolate.Language;
1+
using System.Text;
2+
using System.Text.Json;
33

44
namespace HotChocolate.Fusion.Planning.Nodes;
55

6-
public sealed class RootPlanNode : PlanNode, IOperationPlanNodeProvider
6+
public sealed class RootPlanNode : PlanNode, IPlanNodeProvider, ISerializablePlanNode
77
{
8-
private readonly List<OperationPlanNode> _operations = new();
8+
private static readonly JsonWriterOptions SerializerOptions = new()
9+
{
10+
Indented = true,
11+
};
12+
private readonly List<PlanNode> _nodes = [];
913

10-
public IReadOnlyList<OperationPlanNode> Operations
11-
=> _operations;
14+
public IReadOnlyList<PlanNode> Nodes => _nodes;
1215

13-
public void AddOperation(OperationPlanNode operation)
16+
public void AddChildNode(PlanNode node)
1417
{
15-
ArgumentNullException.ThrowIfNull(operation);
16-
_operations.Add(operation);
17-
operation.Parent = this;
18+
ArgumentNullException.ThrowIfNull(node);
19+
_nodes.Add(node);
20+
node.Parent = this;
1821
}
1922

20-
public DocumentNode ToSyntaxNode()
23+
public PlanNodeKind Kind => PlanNodeKind.Root;
24+
25+
public string Serialize()
2126
{
22-
var backlog = new Queue<OperationPlanNode>();
23-
var definitions = ImmutableArray.CreateBuilder<IDefinitionNode>();
27+
using var memoryStream = new MemoryStream();
28+
var jsonWriter = new Utf8JsonWriter(memoryStream, SerializerOptions);
2429

25-
foreach(var operation in _operations)
26-
{
27-
backlog.Enqueue(operation);
28-
}
30+
Serialize(jsonWriter);
2931

30-
while(backlog.TryDequeue(out var operation))
31-
{
32-
definitions.Add(operation.ToSyntaxNode());
32+
return Encoding.UTF8.GetString(memoryStream.ToArray());
33+
}
3334

34-
foreach(var child in operation.Operations)
35-
{
36-
backlog.Enqueue(child);
37-
}
38-
}
35+
public void Serialize(Utf8JsonWriter writer)
36+
{
37+
writer.WriteStartObject();
38+
SerializationHelper.WriteKind(writer, this);
39+
SerializationHelper.WriteChildNodes(writer, this);
40+
writer.WriteEndObject();
3941

40-
return new DocumentNode(definitions.ToImmutable());
42+
writer.Flush();
4143
}
4244
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Text.Json;
2+
3+
namespace HotChocolate.Fusion.Planning.Nodes;
4+
5+
public static class SerializationHelper
6+
{
7+
public static void WriteChildNodes(Utf8JsonWriter writer, IPlanNodeProvider planNodeProvider)
8+
{
9+
if (planNodeProvider.Nodes.Count == 0)
10+
{
11+
return;
12+
}
13+
14+
writer.WritePropertyName("nodes");
15+
writer.WriteStartArray();
16+
17+
foreach (var node in planNodeProvider.Nodes.OfType<ISerializablePlanNode>())
18+
{
19+
node.Serialize(writer);
20+
}
21+
22+
writer.WriteEndArray();
23+
}
24+
25+
public static void WriteKind(Utf8JsonWriter writer, ISerializablePlanNode serializablePlanNode)
26+
{
27+
writer.WriteString("kind", serializablePlanNode.Kind.ToString());
28+
}
29+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public RootPlanNode CreatePlan(DocumentNode document, string? operationName)
2727

2828
if (TryPlanSelectionSet(operation, operation, new Stack<SelectionPathSegment>()))
2929
{
30-
operationPlan.AddOperation(operation);
30+
operationPlan.AddChildNode(operation);
3131
}
3232
}
3333

@@ -191,7 +191,7 @@ private bool TryHandleUnresolvedSelections(
191191
continue;
192192
}
193193

194-
operation.AddOperation(lookupOperation);
194+
operation.AddChildNode(lookupOperation);
195195

196196
foreach (var selection in lookupField.Selections)
197197
{

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public static void BindOperationVariables(
1414
var variableDefinitions = operationDefinition.VariableDefinitions.ToDictionary(t => t.Variable.Name.Value);
1515
var usedVariables = new HashSet<string>();
1616

17-
foreach (var operation in operationPlan.Operations)
17+
foreach (var operation in operationPlan.Nodes.OfType<OperationPlanNode>())
1818
{
1919
operationBacklog.Push(operation);
2020
}
@@ -23,7 +23,7 @@ public static void BindOperationVariables(
2323
{
2424
CollectAndBindUsedVariables(operation, variableDefinitions, usedVariables, selectionBacklog);
2525

26-
foreach (var child in operation.Operations)
26+
foreach (var child in operation.Nodes.OfType<OperationPlanNode>())
2727
{
2828
operationBacklog.Push(child);
2929
}

0 commit comments

Comments
 (0)