Skip to content

Commit 6c8dc9a

Browse files
authored
Fixed Object Composition for Partial Results. (#6339)
1 parent 77913da commit 6c8dc9a

8 files changed

+458
-39
lines changed

src/HotChocolate/Fusion/src/Core/Execution/ExecutorUtils.cs

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,16 @@ private static void ComposeResult(
6363

6464
if (!data.HasValue)
6565
{
66-
if (!partialResult && !nullable)
66+
if (!partialResult)
6767
{
68-
PropagateNonNullError(selectionSetResult);
69-
break;
70-
}
68+
if (!nullable)
69+
{
70+
PropagateNonNullError(selectionSetResult);
71+
break;
72+
}
7173

72-
result.Set(responseName, null, nullable);
74+
result.Set(responseName, null, nullable);
75+
}
7376
}
7477
else if (namedType.IsType(TypeKind.Scalar))
7578
{
@@ -108,38 +111,44 @@ private static void ComposeResult(
108111
}
109112
else if (selectionType.IsCompositeType())
110113
{
111-
var value = ComposeObject(
112-
context,
113-
selectionSetResult,
114-
responseIndex,
115-
selection,
116-
data);
117-
118-
if (value is null && !nullable)
114+
if (!result.IsInitialized)
119115
{
120-
PropagateNonNullError(selectionSetResult);
121-
break;
122-
}
116+
var value = ComposeObject(
117+
context,
118+
selectionSetResult,
119+
responseIndex,
120+
selection,
121+
data);
122+
123+
if (value is null && !nullable)
124+
{
125+
PropagateNonNullError(selectionSetResult);
126+
break;
127+
}
123128

124-
result.Set(responseName, value, nullable);
129+
result.Set(responseName, value, nullable);
130+
}
125131
}
126132
else
127133
{
128-
var value = ComposeList(
129-
context,
130-
selectionSetResult,
131-
responseIndex,
132-
selection,
133-
data,
134-
selectionType);
135-
136-
if (value is null && !nullable)
134+
if (!result.IsInitialized)
137135
{
138-
PropagateNonNullError(selectionSetResult);
139-
break;
140-
}
136+
var value = ComposeList(
137+
context,
138+
selectionSetResult,
139+
responseIndex,
140+
selection,
141+
data,
142+
selectionType);
143+
144+
if (value is null && !nullable)
145+
{
146+
PropagateNonNullError(selectionSetResult);
147+
break;
148+
}
141149

142-
result.Set(responseName, value, nullable);
150+
result.Set(responseName, value, nullable);
151+
}
143152
}
144153
}
145154
else if ((selection.CustomOptions & _typeNameFlag) == _typeNameFlag)

src/HotChocolate/Fusion/src/Core/Planning/Nodes/Compose.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public Compose(int id, IReadOnlyList<ISelectionSet> selectionSets) : base(id)
2424
throw new ArgumentNullException(nameof(selectionSets));
2525
}
2626

27-
_selectionSets = selectionSets.Distinct().ToArray();
27+
_selectionSets = selectionSets.Distinct().OrderBy(t => t.Id).ToArray();
2828
}
2929

3030
public override QueryPlanNodeKind Kind => QueryPlanNodeKind.Compose;

src/HotChocolate/Fusion/test/Core.Tests/DemoIntegrationTests.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,6 +1345,72 @@ query Requires {
13451345

13461346
Assert.Null(result.ExpectQueryResult().Errors);
13471347
}
1348+
1349+
[Fact]
1350+
public async Task Require_Data_In_Context_3()
1351+
{
1352+
// arrange
1353+
using var demoProject = await DemoProject.CreateAsync();
1354+
1355+
// act
1356+
var fusionGraph = await new FusionGraphComposer(logFactory: _logFactory).ComposeAsync(
1357+
new[]
1358+
{
1359+
demoProject.Reviews2.ToConfiguration(Reviews2ExtensionSdl),
1360+
demoProject.Accounts.ToConfiguration(AccountsExtensionSdl),
1361+
demoProject.Products.ToConfiguration(ProductsExtensionSdl),
1362+
demoProject.Shipping.ToConfiguration(ShippingExtensionSdl),
1363+
},
1364+
FusionFeatureFlags.NodeField);
1365+
1366+
var executor = await new ServiceCollection()
1367+
.AddSingleton(demoProject.HttpClientFactory)
1368+
.AddSingleton(demoProject.WebSocketConnectionFactory)
1369+
.AddFusionGatewayServer()
1370+
.ConfigureFromDocument(SchemaFormatter.FormatAsDocument(fusionGraph))
1371+
.BuildRequestExecutorAsync();
1372+
1373+
var request = Parse(
1374+
"""
1375+
query Large {
1376+
users {
1377+
id
1378+
name
1379+
birthdate
1380+
reviews {
1381+
body
1382+
author {
1383+
name
1384+
birthdate
1385+
}
1386+
product {
1387+
id
1388+
name
1389+
deliveryEstimate(zip: "abc") {
1390+
max
1391+
}
1392+
}
1393+
}
1394+
}
1395+
}
1396+
""");
1397+
1398+
// act
1399+
var result = await executor.ExecuteAsync(
1400+
QueryRequestBuilder
1401+
.New()
1402+
.SetQuery(request)
1403+
.SetVariableValue("id", "UHJvZHVjdAppMQ==")
1404+
.SetVariableValue("first", 1)
1405+
.Create());
1406+
1407+
// assert
1408+
var snapshot = new Snapshot();
1409+
CollectSnapshotData(snapshot, request, result, fusionGraph);
1410+
await snapshot.MatchAsync();
1411+
1412+
Assert.Null(result.ExpectQueryResult().Errors);
1413+
}
13481414

13491415
public sealed class HotReloadConfiguration : IObservable<GatewayConfiguration>
13501416
{

0 commit comments

Comments
 (0)