apollographql / apollographql/federation

[gateway] 🐞 Field resolves to null when combining fragments on interfaces and implementations

Open
#384 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
725
Forks
276
Avg merge
1h 47m
Merged PRs (30d)
1

Description

### Packages
- `@apollo/gateway@0.14.1`
- `@apollo/federation@0.14.1`

### Summary
This issue only exists in the gateway, executing the same query against graphql server yields expected result. The issue is, queried fields return a null value when combining multiple fragments on the interface and its implementations, even though there is a non-null value resolved by the underlying service.

#### Extension to product schema of [federation-demo](https://github.com/apollographql/federation-demo/blob/master/services/products/index.js#L9)
```gql
type Product @key(fields: "upc") {
upc: String!
name: String
price: Int
weight: Int
someProp: ISomeProp # <-- New property
}

type ChildProp {
value: String
}

interface ISomeProp {
childProp: ChildProp
}

type SomeProp_IMPL_1 implements ISomeProp {
childProp: ChildProp
IAM_IMPL_1: Boolean
}

type SomeProp_IMPL_2 implements ISomeProp {
childProp: ChildProp
IAM_IMPL_2: Boolean
}
```

#### Query example
```gql
query {
topProducts(first: 2) {
someProp {
...Frag_SomeProp_IMPL_1
...Frag_ISomeProp
}
}
}

fragment Frag_ISomeProp on ISomeProp {
...Frag_ISomeProp2
}

fragment Frag_SomeProp_IMPL_1 on SomeProp_IMPL_1 {
IAM_IMPL_1
...Frag_ISomeProp2
}

fragment Frag_ISomeProp2 on ISomeProp {
... on SomeProp_IMPL_2 {
IAM_IMPL_2
childProp {
...Frag_ChildProp
}
}
__typename
}

fragment Frag_ChildProp on ChildProp {
__typename
value
}
```

#### Result from gateway
```json
{
"data": {
"topProducts": [
{
"someProp": {
"IAM_IMPL_2": null,
"childProp": null,
"__typename": "SomeProp_IMPL_2"
}
},
{
"someProp": {
"IAM_IMPL_2": null,
"childProp": null,
"__typename": "SomeProp_IMPL_2"
}
}
]
}
}
```

#### Result from product service
```json
{
"data": {
"topProducts": [
{
"someProp": {
"IAM_IMPL_2": true,
"childProp": {
"__typename": "ChildProp",
"value": "childProp value"
},
"__typename": "SomeProp_IMPL_2"
}
},
{
"someProp": {
"IAM_IMPL_2": true,
"childProp": {
"__typename": "ChildProp",
"value": "childProp value"
},
"__typename": "SomeProp_IMPL_2"
}
}
]
}
}
```

### Expected behaviour
Queried fields using fragments should resolve to the actual value instead of null.

### Actual behaviour
Queried fields using fragments are resolved to null.

### Steps to reproduce
- Clone Repository: https://github.com/01alchemist/federation-demo
- `npm install`
- `npm run start-services`
- Open a new terminal
- `npm run start-gateway`
- Execute example query on http://localhost:4000/
- Execute example query on http://localhost:4003/
- Both should return the same result but it's different.

Contributor guide

Open the contributing guide

Research direction

Reproduce the query using the federation-demo extension in services/products/index.js, running the services and gateway at the documented endpoints, then compare the gateway response with the product service response. Trace how the gateway combines fragments on ISomeProp and its implementations; done means the gateway returns the resolved IAM_IMPL_2 and childProp values instead of null.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, typescript
Domain
api, backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.