Skip to content

Commit df2f85d

Browse files
[Fusion] Fix BatchExecutionState with multiple VariableValues (#7982)
1 parent cb62bfd commit df2f85d

4 files changed

+577
-3
lines changed

src/HotChocolate/Fusion/src/Core/Execution/Nodes/ResolveByKeyBatch.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ protected override async Task OnExecuteAsync(
7575
var batchExecutionState = CreateBatchBatchState(executionState, Requires);
7676

7777
// Create the batch subgraph request.
78-
var variableValues = BuildVariables(batchExecutionState, _argumentTypes);
78+
var variableValues = BuildVariables(batchExecutionState, Requires, _argumentTypes);
7979
var request = CreateRequest(context.OperationContext.Variables, variableValues);
8080

8181
// Once we have the batch request, we will enqueue it for execution with
@@ -194,6 +194,7 @@ private void ProcessResult(
194194

195195
private static Dictionary<string, IValueNode> BuildVariables(
196196
BatchExecutionState[] batchExecutionState,
197+
string[] requires,
197198
Dictionary<string, ITypeNode> argumentTypes)
198199
{
199200
var first = batchExecutionState[0];
@@ -220,7 +221,7 @@ private static Dictionary<string, IValueNode> BuildVariables(
220221
batchState = ref Unsafe.Add(ref batchState, 1)!;
221222
}
222223

223-
foreach (var key in first.VariableValues.Keys)
224+
foreach (var key in requires)
224225
{
225226
var expectedType = argumentTypes[key];
226227

@@ -240,7 +241,7 @@ private static Dictionary<string, IValueNode> BuildVariables(
240241
}
241242
else
242243
{
243-
if (batchExecutionState[0].VariableValues.TryGetValue(key, out var variableValue))
244+
if (first.VariableValues.TryGetValue(key, out var variableValue))
244245
{
245246
variableValues.Add(key, variableValue);
246247
}

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

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,6 +1961,223 @@ query TopProducts {
19611961
Assert.Null(result.ExpectOperationResult().Errors);
19621962
}
19631963

1964+
[Fact]
1965+
public async Task BatchExecutionState_With_Multiple_Variable_Values()
1966+
{
1967+
// arrange
1968+
var subgraphA = await TestSubgraph.CreateAsync(
1969+
"""
1970+
type Query {
1971+
node(id: ID!): Node
1972+
nodes(ids: [ID!]!): [Node]!
1973+
}
1974+
1975+
interface Node {
1976+
id: ID!
1977+
}
1978+
1979+
type User implements Node {
1980+
id: ID!
1981+
displayName: String!
1982+
}
1983+
""");
1984+
var subgraphB = await TestSubgraph.CreateAsync(
1985+
"""
1986+
type Query {
1987+
node(id: ID!): Node
1988+
nodes(ids: [ID!]!): [Node]!
1989+
userBySlug(slug: String!): User
1990+
}
1991+
1992+
interface Node {
1993+
id: ID!
1994+
}
1995+
1996+
type User implements Node {
1997+
relativeUrl: String!
1998+
id: ID!
1999+
}
2000+
""");
2001+
var subgraphC = await TestSubgraph.CreateAsync(
2002+
"""
2003+
type Query {
2004+
node(id: ID!): Node
2005+
nodes(ids: [ID!]!): [Node]!
2006+
}
2007+
2008+
interface Node {
2009+
id: ID!
2010+
}
2011+
2012+
type User implements Node {
2013+
id: ID!
2014+
feedbacks: FeedbacksConnection
2015+
}
2016+
2017+
type FeedbacksConnection {
2018+
edges: [FeedbacksEdge!]
2019+
}
2020+
2021+
type FeedbacksEdge {
2022+
node: ResaleFeedback!
2023+
}
2024+
2025+
type ResaleFeedback implements Node {
2026+
feedback: ResaleSurveyFeedback
2027+
id: ID!
2028+
}
2029+
2030+
type ResaleSurveyFeedback {
2031+
buyer: User
2032+
}
2033+
""");
2034+
2035+
using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB, subgraphC]);
2036+
var executor = await subgraphs.GetExecutorAsync();
2037+
2038+
var request = Parse(
2039+
"""
2040+
query {
2041+
userBySlug(slug: "me") {
2042+
feedbacks {
2043+
edges {
2044+
node {
2045+
feedback {
2046+
buyer {
2047+
relativeUrl
2048+
displayName
2049+
}
2050+
}
2051+
}
2052+
}
2053+
}
2054+
}
2055+
}
2056+
2057+
""");
2058+
2059+
// act
2060+
await using var result = await executor.ExecuteAsync(
2061+
OperationRequestBuilder
2062+
.New()
2063+
.SetDocument(request)
2064+
.Build());
2065+
2066+
// assert
2067+
var snapshot = new Snapshot();
2068+
CollectSnapshotData(snapshot, request, result);
2069+
await snapshot.MatchMarkdownAsync();
2070+
}
2071+
2072+
[Fact]
2073+
public async Task BatchExecutionState_With_Multiple_Variable_Values_And_Forwarded_Variable()
2074+
{
2075+
// arrange
2076+
var subgraphA = await TestSubgraph.CreateAsync(
2077+
"""
2078+
type Query {
2079+
node(id: ID!): Node
2080+
nodes(ids: [ID!]!): [Node]!
2081+
}
2082+
2083+
interface Node {
2084+
id: ID!
2085+
}
2086+
2087+
type User implements Node {
2088+
id: ID!
2089+
displayName(arg: String): String!
2090+
}
2091+
""");
2092+
var subgraphB = await TestSubgraph.CreateAsync(
2093+
"""
2094+
type Query {
2095+
node(id: ID!): Node
2096+
nodes(ids: [ID!]!): [Node]!
2097+
userBySlug(slug: String!): User
2098+
}
2099+
2100+
interface Node {
2101+
id: ID!
2102+
}
2103+
2104+
type User implements Node {
2105+
relativeUrl(arg: String): String!
2106+
id: ID!
2107+
}
2108+
""");
2109+
var subgraphC = await TestSubgraph.CreateAsync(
2110+
"""
2111+
type Query {
2112+
node(id: ID!): Node
2113+
nodes(ids: [ID!]!): [Node]!
2114+
}
2115+
2116+
interface Node {
2117+
id: ID!
2118+
}
2119+
2120+
type User implements Node {
2121+
id: ID!
2122+
feedbacks: FeedbacksConnection
2123+
}
2124+
2125+
type FeedbacksConnection {
2126+
edges: [FeedbacksEdge!]
2127+
}
2128+
2129+
type FeedbacksEdge {
2130+
node: ResaleFeedback!
2131+
}
2132+
2133+
type ResaleFeedback implements Node {
2134+
feedback: ResaleSurveyFeedback
2135+
id: ID!
2136+
}
2137+
2138+
type ResaleSurveyFeedback {
2139+
buyer: User
2140+
}
2141+
""");
2142+
2143+
using var subgraphs = new TestSubgraphCollection(output, [subgraphA, subgraphB, subgraphC]);
2144+
var executor = await subgraphs.GetExecutorAsync();
2145+
2146+
var request = Parse(
2147+
"""
2148+
query($arg1: String, $arg2: String) {
2149+
userBySlug(slug: "me") {
2150+
feedbacks {
2151+
edges {
2152+
node {
2153+
feedback {
2154+
buyer {
2155+
relativeUrl(arg: $arg1)
2156+
displayName(arg: $arg2)
2157+
}
2158+
}
2159+
}
2160+
}
2161+
}
2162+
}
2163+
}
2164+
2165+
""");
2166+
2167+
// act
2168+
await using var result = await executor.ExecuteAsync(
2169+
OperationRequestBuilder
2170+
.New()
2171+
.SetDocument(request)
2172+
.SetVariableValues(new Dictionary<string, object?> { ["arg1"] = "abc", ["arg2"] = "def" })
2173+
.Build());
2174+
2175+
// assert
2176+
var snapshot = new Snapshot();
2177+
CollectSnapshotData(snapshot, request, result);
2178+
await snapshot.MatchMarkdownAsync();
2179+
}
2180+
19642181
public sealed class HotReloadConfiguration : IObservable<GatewayConfiguration>
19652182
{
19662183
private GatewayConfiguration _configuration;

0 commit comments

Comments
 (0)