-
Notifications
You must be signed in to change notification settings - Fork 28
Description
Hello Hive maintainers,
I observed a behavior with the @graphql-tools/stitch library that doesn't make sense to me. I would appreciate if you could take a look at it and let me know if you consider this to be a bug.
In my scenario the library makes two requests to the same subschema for one incoming query where the second call appears to be redundant. In my tests this resulted in even wrong data returned by the gateway if the order of collections is not the exact same for the first and second subschema request.
Minimal Example
I attempted to reproduce it and assembled a minimal example showing this behavior here: https://github.com/JoergBastian/gql-stitching-redundant-calls-mre
The example with which I was able to reproduce this uses only one subschema. It consists of one subschema and one gateway, both using GraphQL Yoga. Stitching Directives from @graphql-tools/stitching-directives are used.
The behavior seems to be related to both the Query field box and the Box type using the @canonical directive. They are using this directive as in my real-life application the Box type would be extended by other subschemas.
SDL Excerpt:
type Query {
box(id: ID!): Box @merge(keyField: "id") @canonical
}
type Box @canonical {
id: ID!
items(shuffle: Boolean): [Item]
}Observed behavior
I execute the following query against the gateway:
{
box(id: "1") {
items {
name,
...on Edible {
calories
}
}
}
}The gateway logs two outgoing queries to the subschema:
Query #1: {
__typename
box(id: "1") {
__typename
id
id
items {
__typename
name
... on Edible {
calories
}
}
}
}
Query #2: query ($id: ID!) {
__typename
box(id: $id) {
__typename
id
items {
__typename
}
}
}
Looking at the second query, I fail to understand why it is made as all information queried should already be present in the first response.
The response is correct if the collection items is unchanged for the first and second call to the subschema. However, if the order of the items is changed between the first and second call, the types will be mixed up and fields missing that should be there.
Correct response
{
"data": {
"box": {
"id": "1",
"items": [
{
"name": "Apple",
"calories": 95
},
{
"name": "Banana",
"calories": 105
},
{
"name": "Cherry",
"calories": 50
},
{
"name": "Pen"
}
]
}
}
}Response when shuffeled
{
"data": {
"box": {
"id": "1",
"items": [
{
"name": "Pen",
"calories": null
},
{
"name": "Cherry",
"calories": 50
},
{
"name": "Banana",
"calories": 105
},
{
"name": "Apple"
}
]
}
}
}In the example, the Apple should have a calories field, the Pen shouldn't. If the schema is changed to require calories to not be null, the query will fail.