apollographql / apollographql/federation

Redundant queries (similar to N+1) if same type is present in multiple places

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

Description

**Describe the bug**
If objects of the same type is present in different `paths` , multople requests are made to fetch the same resource

**To Reproduce**
Full setup here: https://github.com/ahrushetskyi/apollo_fed_np1

Subgraph A:

```graphql
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0")

type Action @federation__key(fields: "id") {
config: ActionConfig!
defaultTemplate: Template!
delay: Int!
id: ID!
}

union ActionConfig = ConfigOne | ConfigThree | ConfigTwo

type ConfigOne {
id: ID!
otherTemplate: Template!
someTemplate: Template!
}

type ConfigThree {
id: ID!
wrongTemplate: Template!
}

type ConfigTwo {
id: ID!
leftTemplate: Template!
rightTemplate: Template!
}

type Query {
actions: [Action!]!
}

type Template @federation__extends @federation__key(fields: "id") {
id: ID!
}
```
Subgraph B

```graphql
extend schema
@link(url: "https://specs.apollo.dev/federation/v2.0")

type Template @federation__key(fields: "id") {
body: String!
id: ID!
name: String!
}
```
Query:
```graphql
query ExampleQuery {
actions {
config {
... on ConfigOne {
id
otherTemplate {
name
body
id
}
someTemplate {
name
body
id
}
}
... on ConfigThree {
id
wrongTemplate {
name
body
id
}
}
... on ConfigTwo {
id
leftTemplate {
name
body
id
}
rightTemplate {
name
body
id
}
}
}
}
}

```
Query plan

```graphql
QueryPlan {
Sequence {
Fetch(service: "schemaA") {
{
actions {
config {
__typename
... on ConfigOne {
id
otherTemplate {
__typename
id
}
someTemplate {
__typename
id
}
}
... on ConfigThree {
id
wrongTemplate {
__typename
id
}
}
... on ConfigTwo {
id
leftTemplate {
__typename
id
}
rightTemplate {
__typename
id
}
}
}
}
}
},
Parallel {
Flatten(path: "actions.@.config.otherTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.someTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.wrongTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.leftTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
Flatten(path: "actions.@.config.rightTemplate") {
Fetch(service: "schemaB") {
{
... on Template {
__typename
id
}
} =>
{
... on Template {
name
body
}
}
},
},
},
},
}
```
![image](https://user-images.githubusercontent.com/2060984/193574704-7e2b8329-d593-4da2-93fb-7a0e15f9291b.png)

**Expected behavior**

It should not perform 5 queries to fetch `Template`s. It is possible to do that in one query

**Versions:**

`rover -V`: Rover 0.9.0
`./router -V`: 1.0.0

Contributor guide

Open the contributing guide

Research direction

Start with the linked reproduction repository and inspect the generated QueryPlan for the federated query shown here, focusing on the five parallel fetches to schemaB. Compare the plan with the expected behavior in the issue; done means the reproduction no longer performs five separate Template fetches.

Written by the indexing model from the issue text.

Assessment

Tech stack
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
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.