Skip to content

Commit 3571399

Browse files
authored
fix(federation): shared mutation field should not be batched (#387)
1 parent 47e99b0 commit 3571399

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

.changeset/smart-wasps-smile.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@graphql-tools/federation': patch
3+
---
4+
5+
In case of shared root field on Mutation, it was batched incorrectly across subgraphs. But instead only one mutation should be called as mutations should not be parallel

packages/federation/src/supergraph.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1207,7 +1207,11 @@ export function getStitchingOptionsFromSupergraphSdl(
12071207
return candidates[0].fieldConfig;
12081208
}
12091209
}
1210-
if (candidates.some((candidate) => rootTypeMap.has(candidate.type.name))) {
1210+
if (
1211+
candidates.some(
1212+
(candidate) => rootTypeMap.get(candidate.type.name) === 'query',
1213+
)
1214+
) {
12111215
const defaultMergedField = defaultMerger(candidates);
12121216
return {
12131217
...defaultMergedField,

packages/federation/tests/aliased-shared-root.test.ts packages/federation/tests/shared-root.test.ts

+77-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { buildSubgraphSchema } from '@apollo/subgraph';
22
import { normalizedExecutor } from '@graphql-tools/executor';
3-
import { parse } from 'graphql';
4-
import { describe, expect, it } from 'vitest';
3+
import { ExecutionRequest } from '@graphql-tools/utils';
4+
import { ExecutionResult, parse } from 'graphql';
5+
import { describe, expect, it, vi } from 'vitest';
56
import { getStitchedSchemaFromLocalSchemas } from './getStitchedSchemaFromLocalSchemas';
67

7-
describe('Aliased Shared Root Fields', () => {
8-
it('issue #6613', async () => {
8+
describe('Shared Root Fields', () => {
9+
it('Aliased shared root fields issue #6613', async () => {
910
const query = /* GraphQL */ `
1011
query {
1112
testNestedField {
@@ -109,4 +110,76 @@ describe('Aliased Shared Root Fields', () => {
109110

110111
expect(result).toEqual(expectedResult);
111112
});
113+
it('Mutations should not be batched', async () => {
114+
const SUBGRAPHA = buildSubgraphSchema({
115+
typeDefs: parse(/* GraphQL */ `
116+
type Query {
117+
test: String
118+
}
119+
120+
type Mutation {
121+
testMutation: String
122+
}
123+
`),
124+
resolvers: {
125+
Query: {
126+
test: () => 'test',
127+
},
128+
Mutation: {
129+
testMutation: () => 'testMutation',
130+
},
131+
},
132+
});
133+
const SUBGRAPHB = buildSubgraphSchema({
134+
typeDefs: parse(/* GraphQL */ `
135+
type Query {
136+
test: String
137+
}
138+
139+
type Mutation {
140+
testMutation: String
141+
}
142+
`),
143+
resolvers: {
144+
Query: {
145+
test: () => 'test',
146+
},
147+
Mutation: {
148+
testMutation: () => 'testMutation',
149+
},
150+
},
151+
});
152+
const onSubgraphExecuteFn =
153+
vi.fn<
154+
(
155+
subgraph: string,
156+
executionRequest: ExecutionRequest,
157+
result: ExecutionResult | AsyncIterable<ExecutionResult>,
158+
) => void
159+
>();
160+
const gatewaySchema = await getStitchedSchemaFromLocalSchemas(
161+
{
162+
SUBGRAPHA,
163+
SUBGRAPHB,
164+
},
165+
onSubgraphExecuteFn,
166+
);
167+
168+
const result = await normalizedExecutor({
169+
schema: gatewaySchema,
170+
document: parse(/* GraphQL */ `
171+
mutation {
172+
testMutation
173+
}
174+
`),
175+
});
176+
177+
expect(result).toEqual({
178+
data: {
179+
testMutation: 'testMutation',
180+
},
181+
});
182+
183+
expect(onSubgraphExecuteFn).toHaveBeenCalledTimes(1);
184+
});
112185
});

0 commit comments

Comments
 (0)