router icon indicating copy to clipboard operation
router copied to clipboard

specify the path instead of creating a deferred response from the root

Open Geal opened this issue 2 years ago • 4 comments

on this query:

query ProductById {
  product(id: "apollo-federation") {
    id
    ... on ProductItf @defer {
      package
    }
  }
}

we get:

{
  "data": {
    "product": {
      "id": "apollo-federation"
    }
  },
  "hasNext": true
}

then:

{
  "data": {
    "product": {
      "package": "@apollo/federation"
    }
  },
  "hasNext": true
}

while the second response should be:

{
  "data": {
    "package": "@apollo/federation"
  },
  "path": [ "product" ],
  "hasNext": true
}

Geal avatar Aug 05 '22 08:08 Geal

An example with lists.

Query

query AllProducts {
  allProducts {
    id
    ... on Product @defer {
      hidden
    }
  }
}

Router current behavior

{"data":{"allProducts":[{"id":"apollo-federation"},{"id":"apollo-studio"}]},"hasNext":true}
{"data":{"allProducts":[{},{}]},"hasNext":true}
{"hasNext":false}

What we would expect

{"data":{"allProducts":[{"id":"apollo-federation"},{"id":"apollo-studio"}]},"hasNext":true}
{"data":{"hidden":null},"path":["allProducts",0],"hasNext":true}
{"data":{"hidden":null},"path":["allProducts",1],"hasNext":false}

We never expect to have to merge lists, instead we expect each item to have its own payload. This allows the client to know at each payload what has been received or not.

BoD avatar Aug 05 '22 09:08 BoD

that one with lists is unlikely to happen, considering how the query plan is built. And the separate {"hasNext":false} is necessary because there's no reliable way to know when a deferred response is the last one

Geal avatar Aug 05 '22 13:08 Geal

The separate {"hasNext":false} is not an issue on our side 👍

For the lists: to clarify, on our side, the need is to have a 1:1 mapping between payloads and deferred fragments.

BoD avatar Aug 05 '22 13:08 BoD

The separate {"hasNext":false} is also not an issue on our side. We would, however, also expect each item in a list to have its own payload.

Given https://github.com/robrichard/defer-stream-wg/discussions/46, can we consider this question similarly resolved?

alessbell avatar Aug 09 '22 14:08 alessbell

ok so #1529 should fix it, and the good news is that after thinking about this for a while, the only correct way I see to implement it solves both points at once, using a path prefix and generating one response per list element

Geal avatar Aug 17 '22 11:08 Geal

@BoD @alessbell this will go in the next release, probably early next week

Geal avatar Aug 18 '22 15:08 Geal

very cool! 🙏

BoD avatar Aug 18 '22 15:08 BoD

Tested with v0.16.0, it's looking good on Apollo Kotlin's side! 🎉

BoD avatar Aug 22 '22 16:08 BoD

Nice :smile:

Geal avatar Aug 22 '22 16:08 Geal