Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fusion] Enrich Operation Plan Snapshots #7816

Merged
merged 3 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
using HotChocolate.Language;

namespace HotChocolate.Fusion.Planning.Nodes;

public sealed class RootPlanNode : PlanNode
public sealed class RequestPlanNode : PlanNode
{
private readonly List<OperationPlanNode> _operations = [];

public RequestPlanNode(DocumentNode document, string? operationName = null)
{
Document = document;
OperationName = operationName;
}

public DocumentNode Document { get; }

public string? OperationName { get; }

public IReadOnlyList<OperationPlanNode> Operations => _operations;

public void AddOperation(OperationPlanNode node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ public sealed class OperationPlanner(CompositeSchema schema)
{
private int _lastRequirementId;

public RootPlanNode CreatePlan(DocumentNode document, string? operationName)
public RequestPlanNode CreatePlan(DocumentNode document, string? operationName)
{
ArgumentNullException.ThrowIfNull(document);

var operationDefinition = document.GetOperation(operationName);
var schemasWeighted = GetSchemasWeighted(schema.QueryType, operationDefinition.SelectionSet);
var operationPlan = new RootPlanNode();
var operationPlan = new RequestPlanNode(document, operationName);

// this need to be rewritten to check if everything is planned for.
foreach (var schemaName in schemasWeighted.OrderByDescending(t => t.Value).Select(t => t.Key))
Expand Down Expand Up @@ -709,11 +709,6 @@ public record UnresolvedType(
InlineFragmentNode InlineFragment,
CompositeComplexType TypeCondition);

public class RequestPlanNode
{
public ICollection<OperationPlanNode> Operations { get; } = new List<OperationPlanNode>();
}

private record struct LookupOperation(
OperationPlanNode Operation,
FieldPlanNode Field);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ internal static class OperationVariableBinder
{
public static void BindOperationVariables(
OperationDefinitionNode operationDefinition,
RootPlanNode operationPlan)
RequestPlanNode operationPlan)
{
var operationBacklog = new Stack<OperationPlanNode>(operationPlan.Operations.OfType<OperationPlanNode>());
var selectionBacklog = new Stack<SelectionPlanNode>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ namespace HotChocolate.Fusion.Planning;

public static class PlanNodeJsonFormatter
{
public static string ToJson(this RootPlanNode root)
public static string ToJson(this RequestPlanNode request)
{
var buffer = new ArrayBufferWriter<byte>();
var writer = new Utf8JsonWriter(buffer, new JsonWriterOptions { Indented = true });
writer.Write(root);
writer.Write(request);
writer.Flush();
return Encoding.UTF8.GetString(buffer.WrittenSpan);
}

public static void Write(this Utf8JsonWriter writer, RootPlanNode root)
public static void Write(this Utf8JsonWriter writer, RequestPlanNode request)
{
var nodeIdLookup = CollectNodeIds(root);
var nodeIdLookup = CollectNodeIds(request);

writer.WriteStartObject();

Expand Down Expand Up @@ -105,7 +105,7 @@ private static Dictionary<OperationPlanNode, int> CollectNodeIds(PlanNode root)

while (backlog.TryDequeue(out var node))
{
if (node is RootPlanNode rootPlanNode)
if (node is RequestPlanNode rootPlanNode)
{
foreach (var child in rootPlanNode.Operations)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,38 @@ namespace HotChocolate.Fusion.Planning;

public static class PlanNodeYamlFormatter
{
public static string ToYaml(this RootPlanNode root)
public static string ToYaml(this RequestPlanNode request)
{
var sb = new StringBuilder();
var writer = new StringWriter(sb);
Write(writer, root);
Write(writer, request);
writer.Flush();
return sb.ToString();
}

public static void Write(this StringWriter writer, RootPlanNode root)
public static void Write(this StringWriter writer, RequestPlanNode request)
{
var nodeIdLookup = CollectNodeIds(root);
var nodeIdLookup = CollectNodeIds(request);

writer.WriteLine("request:");
writer.WriteLine(" - document: >-");

var reader = new StringReader(request.Document.ToString());
while (true)
{
var line = reader.ReadLine();
if (line is null)
{
break;
}

writer.WriteLine(" {0}", line);
}

if (!string.IsNullOrEmpty(request.OperationName))
{
writer.WriteLine(" - operationName: \"{0}\"", request.OperationName);
}

writer.WriteLine("nodes:");

Expand Down Expand Up @@ -84,7 +104,7 @@ private static Dictionary<OperationPlanNode, int> CollectNodeIds(PlanNode root)

while (backlog.TryDequeue(out var node))
{
if (node is RootPlanNode rootPlanNode)
if (node is RequestPlanNode rootPlanNode)
{
foreach (var child in rootPlanNode.Operations)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using HotChocolate.Fusion.Planning;
using HotChocolate.Fusion.Planning.Nodes;

namespace HotChocolate.Fusion;

public static class TestSnapshotExtensions
{
public static void MatchSnapshot(this RequestPlanNode plan)
{
plan.ToYaml().MatchSnapshot(extension: ".yaml");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ protected static CompositeSchema CreateCompositeSchema()
return CompositeSchemaBuilder.Create(compositeSchemaDoc);
}

protected static RootPlanNode PlanOperationAsync(CompositeSchema compositeSchema, string operation)
protected static RequestPlanNode PlanOperationAsync(CompositeSchema compositeSchema, string operation)
{
var doc = Utf8GraphQLParser.Parse(operation);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,7 @@ fragment Product on Product {
""");

// assert
plan.ToYaml().MatchInlineSnapshot(
"""
nodes:
- id: 1
schema: "PRODUCTS"
operation: >-
{
productById(id: 1) {
id
name
}
}

""");
plan.MatchSnapshot();
}

[Test]
Expand All @@ -69,35 +56,7 @@ fragment Product on Product {
""");

// assert
plan.ToYaml().MatchInlineSnapshot(
"""
nodes:
- id: 1
schema: "PRODUCTS"
operation: >-
{
productById(id: 1) {
id
name
id
}
}
- id: 2
schema: "SHIPPING"
operation: >-
query($__fusion_requirement_1: ID!) {
productById(id: $__fusion_requirement_1) {
estimatedDelivery(postCode: "12345")
}
}
requirements:
- name: "__fusion_requirement_1"
dependsOn: "1"
selectionSet: "productById"
field: "id"
type: "ID!"

""");
plan.MatchSnapshot();
}

[Test]
Expand Down Expand Up @@ -139,56 +98,7 @@ fragment AuthorCard on UserProfile {
""");

// assert
plan.ToYaml().MatchInlineSnapshot(
"""
nodes:
- id: 1
schema: "PRODUCTS"
operation: >-
{
productById(id: 1) {
name
id
}
}
- id: 2
schema: "REVIEWS"
operation: >-
query($__fusion_requirement_2: ID!) {
productById(id: $__fusion_requirement_2) {
reviews(first: 10) {
nodes {
body
stars
author {
id
}
}
}
}
}
requirements:
- name: "__fusion_requirement_2"
dependsOn: "1"
selectionSet: "productById"
field: "id"
type: "ID!"
- id: 3
schema: "ACCOUNTS"
operation: >-
query($__fusion_requirement_1: ID!) {
userById(id: $__fusion_requirement_1) {
displayName
}
}
requirements:
- name: "__fusion_requirement_1"
dependsOn: "2"
selectionSet: "productById.reviews.nodes.author"
field: "id"
type: "ID!"

""");
plan.MatchSnapshot();
}

[Test]
Expand Down Expand Up @@ -230,56 +140,7 @@ fragment AuthorCard on UserProfile {
""");

// assert
plan.ToYaml().MatchInlineSnapshot(
"""
nodes:
- id: 1
schema: "PRODUCTS"
operation: >-
query($id: ID!) {
productById(id: $id) {
name
id
}
}
- id: 2
schema: "REVIEWS"
operation: >-
query($__fusion_requirement_2: ID!, $first: Int! = 10) {
productById(id: $__fusion_requirement_2) {
reviews(first: $first) {
nodes {
body
stars
author {
id
}
}
}
}
}
requirements:
- name: "__fusion_requirement_2"
dependsOn: "1"
selectionSet: "productById"
field: "id"
type: "ID!"
- id: 3
schema: "ACCOUNTS"
operation: >-
query($__fusion_requirement_1: ID!) {
userById(id: $__fusion_requirement_1) {
displayName
}
}
requirements:
- name: "__fusion_requirement_1"
dependsOn: "2"
selectionSet: "productById.reviews.nodes.author"
field: "id"
type: "ID!"

""");
plan.MatchSnapshot();
}

[Test]
Expand Down Expand Up @@ -313,19 +174,6 @@ ... @include(if: true) {
var plan = planner.CreatePlan(rewritten, null);

// assert
plan.ToYaml().MatchInlineSnapshot(
"""
nodes:
- id: 1
schema: "PRODUCTS"
operation: >-
{
productById(id: 1) {
id
name
}
}

""");
plan.MatchSnapshot();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
request:
- document: >-
{
productById(id: 1) {
id
name
}
}
nodes:
- id: 1
schema: "PRODUCTS"
operation: >-
{
productById(id: 1) {
id
name
}
}
Loading
Loading