Skip to content

Commit 9e0fa33

Browse files
Add errors for leaf fields
1 parent 726f05d commit 9e0fa33

15 files changed

+714
-128
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Text.Json;
2+
3+
namespace HotChocolate.Fusion.Execution.Clients;
4+
5+
// TODO: Add docs
6+
public sealed class ErrorTrie : Dictionary<object, ErrorTrie>
7+
{
8+
public JsonElement Error { get; private set; }
9+
10+
public static ErrorTrie? From(JsonElement json)
11+
{
12+
if (json.ValueKind != JsonValueKind.Array)
13+
{
14+
return null;
15+
}
16+
17+
var root = new ErrorTrie();
18+
19+
foreach (var error in json.EnumerateArray())
20+
{
21+
var currentTrie = root;
22+
23+
if (!error.TryGetProperty("path", out var path) || path.ValueKind != JsonValueKind.Array)
24+
{
25+
continue;
26+
}
27+
28+
foreach (var pathSegment in path.EnumerateArray())
29+
{
30+
object? pathSegmentValue = pathSegment.ValueKind switch
31+
{
32+
JsonValueKind.String => pathSegment.GetString(),
33+
JsonValueKind.Number => pathSegment.GetInt32(),
34+
_ => null
35+
};
36+
37+
if (pathSegmentValue is null)
38+
{
39+
break;
40+
}
41+
42+
if (currentTrie.TryGetValue(pathSegmentValue, out var trieAtPath))
43+
{
44+
currentTrie = trieAtPath;
45+
}
46+
else
47+
{
48+
var newTrie = new ErrorTrie();
49+
currentTrie[pathSegmentValue] = newTrie;
50+
currentTrie = newTrie;
51+
}
52+
}
53+
54+
currentTrie.Error = error;
55+
}
56+
57+
return root;
58+
}
59+
}

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Execution/Clients/SourceSchemaResult.cs

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,6 @@ public sealed class SourceSchemaResult : IDisposable
66
{
77
private readonly IDisposable? _resource;
88

9-
public SourceSchemaResult(Path path, JsonDocument document, FinalMessage final = FinalMessage.Undefined)
10-
{
11-
ArgumentNullException.ThrowIfNull(path);
12-
ArgumentNullException.ThrowIfNull(document);
13-
14-
_resource = document;
15-
Path = path;
16-
17-
var root = document.RootElement;
18-
if (root.ValueKind != JsonValueKind.Object)
19-
{
20-
return;
21-
}
22-
23-
if (root.TryGetProperty("data", out var data))
24-
{
25-
Data = data;
26-
}
27-
28-
if (root.TryGetProperty("errors", out var errors))
29-
{
30-
Errors = errors;
31-
}
32-
33-
if (root.TryGetProperty("extensions", out var extensions))
34-
{
35-
Extensions = extensions;
36-
}
37-
38-
Final = final;
39-
}
40-
419
public SourceSchemaResult(
4210
Path path,
4311
IDisposable resource,
@@ -52,7 +20,7 @@ public SourceSchemaResult(
5220
_resource = resource;
5321
Path = path;
5422
Data = data;
55-
Errors = errors;
23+
Errors = ErrorTrie.From(errors);
5624
Extensions = extensions;
5725
Final = final;
5826
}
@@ -61,7 +29,7 @@ public SourceSchemaResult(
6129

6230
public JsonElement Data { get; }
6331

64-
public JsonElement Errors { get; }
32+
public ErrorTrie? Errors { get; }
6533

6634
public JsonElement Extensions { get; }
6735

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Execution/Nodes/OperationExecutionNode.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,15 +139,33 @@ private async Task<ExecutionNodeResult> ExecuteInternalAsync(
139139
};
140140

141141
var client = context.GetClient(SchemaName, Operation.Operation);
142-
var response = await client.ExecuteAsync(context, request, cancellationToken);
142+
SourceSchemaClientResponse response;
143143

144-
if (!response.IsSuccessful)
144+
try
145+
{
146+
response = await client.ExecuteAsync(context, request, cancellationToken);
147+
148+
if (!response.IsSuccessful)
149+
{
150+
context.AddException();
151+
152+
return new ExecutionNodeResult(
153+
Id,
154+
Activity.Current,
155+
ExecutionStatus.Failed,
156+
Stopwatch.GetElapsedTime(start));
157+
}
158+
}
159+
catch (Exception exception)
145160
{
161+
context.AddException(exception);
162+
146163
return new ExecutionNodeResult(
147164
Id,
148165
Activity.Current,
149166
ExecutionStatus.Failed,
150-
Stopwatch.GetElapsedTime(start));
167+
Stopwatch.GetElapsedTime(start),
168+
exception);
151169
}
152170

153171
var index = 0;
@@ -163,7 +181,7 @@ private async Task<ExecutionNodeResult> ExecuteInternalAsync(
163181

164182
context.AddPartialResults(Source, buffer.AsSpan(0, index));
165183
}
166-
catch
184+
catch (Exception exception)
167185
{
168186
// if there is an error, we need to make sure that the pooled buffers for the JsonDocuments
169187
// are returned to the pool.
@@ -173,7 +191,14 @@ private async Task<ExecutionNodeResult> ExecuteInternalAsync(
173191
result?.Dispose();
174192
}
175193

176-
throw;
194+
context.AddException(exception);
195+
196+
return new ExecutionNodeResult(
197+
Id,
198+
Activity.Current,
199+
ExecutionStatus.Failed,
200+
Stopwatch.GetElapsedTime(start),
201+
exception);
177202
}
178203
finally
179204
{

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Execution/Nodes/Selection.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ public bool IsIncluded(ulong includeFlags)
100100
return false;
101101
}
102102

103+
public override string ToString()
104+
{
105+
return Field.Name;
106+
}
107+
103108
internal void Seal(SelectionSet selectionSet)
104109
{
105110
if ((_flags & Flags.Sealed) == Flags.Sealed)

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Execution/OperationPlanContext.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ internal void AddPartialResults(SelectionPath sourcePath, ReadOnlySpan<SourceSch
105105
internal void AddPartialResults(ObjectResult result, ReadOnlySpan<Selection> selections)
106106
=> _resultStore.AddPartialResults(result, selections);
107107

108+
internal void AddException(Exception? exception = null)
109+
{
110+
// TODO: Implement and change name
111+
}
112+
108113
internal PooledArrayWriter CreateRentedBuffer()
109114
=> _resultStore.CreateRentedBuffer();
110115

src/HotChocolate/Fusion-vnext/src/Fusion.Execution/Execution/Pipeline/OperationPlanMiddleware.cs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using HotChocolate.Execution;
22
using HotChocolate.Fusion.Planning;
33
using HotChocolate.Fusion.Rewriters;
4-
using HotChocolate.Language;
54
using Microsoft.Extensions.DependencyInjection;
65

76
namespace HotChocolate.Fusion.Execution.Pipeline;
@@ -39,26 +38,11 @@ public ValueTask InvokeAsync(RequestContext context, RequestDelegate next)
3938
var operationHash = context.OperationDocumentInfo.Hash.Value;
4039
var operationShortHash = operationHash[..8];
4140
var rewritten = _rewriter.RewriteDocument(operationDocumentInfo.Document, context.Request.OperationName);
42-
var operation = GetOperation(rewritten);
41+
var operation = rewritten.GetOperation(context.Request.OperationName);
4342
var executionPlan = _planner.CreatePlan(operationId, operationHash, operationShortHash, operation);
4443
context.SetOperationPlan(executionPlan);
4544

4645
return next(context);
47-
48-
// TODO: this algorithm is wrong and will fail with multiple operations.
49-
static OperationDefinitionNode GetOperation(DocumentNode document)
50-
{
51-
for (var i = 0; i < document.Definitions.Count; i++)
52-
{
53-
if (document.Definitions[i] is OperationDefinitionNode operation)
54-
{
55-
return operation;
56-
}
57-
}
58-
59-
throw new InvalidOperationException(
60-
"The operation document does not contain an operation definition.");
61-
}
6246
}
6347

6448
public static RequestMiddleware Create()

0 commit comments

Comments
 (0)