mercurius-js / mercurius

Implement GraphQL servers and gateways with Fastify
https://mercurius.dev/
MIT License
2.36k stars 238 forks source link

feat: Implement @live, @stream, @defer #342

Open PacoDu opened 4 years ago

PacoDu commented 4 years ago

It would be awesome to support these directives, see: https://www.apollographql.com/blog/new-features-in-graphql-batch-defer-stream-live-and-subscribe-7585d0c28b07/

I haven't found any implementation yet but I read this will be part of apollo 3.0.

I have no idea how to achieve this feature yet, and this is probably linked to a client implementation. Maybe also a mercurius-client package ?

mcollina commented 4 years ago

That article is 2016. I'm not sure what happened to those but they are likely outside of their plans or already implemented.

PacoDu commented 4 years ago

It's on the 3.0 roadmap of Apollo, I'm on the phone right now i don't have the link

PacoDu commented 4 years ago

https://github.com/apollographql/apollo-client/blob/master/ROADMAP.md#after-apollo-client-30

PacoDu commented 4 years ago

not sure about @live and @stream they are covered by subscriptions but @defer seems quite handy and it's implemented in apollo client https://www.apollographql.com/docs/react/v2.4/features/defer-support/

spec: https://github.com/apollographql/apollo-server/blob/defer-support/docs/source/defer-support.md

PacoDu commented 4 years ago

About the stream version:

I'm experimenting with inter service communication or background tasks with federated services, and I would like to reuse the existing graphql interface available for the federation to avoid the addition of an other communication layer.

And I've some cases where I would like to pull a large amount of data from an API for example to do some batch processing, and currently, using the graphql interface I have to chunk the data and send multiple search query. It would be awesome if I could do something like:

client:

const streamQuery = `
  query {
      searchResource(criterias: { status: PENDING }) @stream {
         id
         name
         status
       }
   }
`
// or
// const streamQuery = `
//   stream {
//       searchResource(criterias: { status: PENDING }) {
//          id
//          name
//          status
//        }
//    }

const client = new GraphQLClient('http://localhost:3000')

const stream = await client.query(query, variables)
for await (const data of stream) {
  const resource = JSON.parse(data)
  // do something
}
`

The graphql query would not return an application/json body but an application/octet-stream. This would be similar in a way to libraries like graphql-upload, apollo-link-form-data or subscriptions that change the communication format/protocol.

@mcollina Idk if this is a non-sense and there is a better way to achieve this, what do you think ? I feel like this is different from the subscriptions that offers a long running connection, and sending a query other the websocket would just result in one large message replied through the websocket.

mcollina commented 4 years ago

I think we'd need to implement a server-to-server client as well to take use of that properly. I'm overall ok with the idea, however the implementation is complex.

Would you like to kickstart a repo in the org and try to experiment?

PacoDu commented 4 years ago

Would you like to kickstart a repo in the org and try to experiment?

Sure, I'll take a look when I've some time available. Should it rely on https://github.com/ndjson/ndjson-spec or something similar ?

mcollina commented 4 years ago

I would do that, yes.

edno commented 3 years ago

It would be great to support @defer and @stream since the RFC is making good progress.

PacoDu commented 3 years ago

@edno I didn't even know about the RFC, thanks ! I don't have time to work on this feature right now, feel free to open a PR !

robertherber commented 3 years ago

Support for this would be awesome! Any updates on this?

This blogpost could provides some more context, with examples: https://graphql.org/blog/2020-12-08-improving-latency-with-defer-and-stream-directives

mcollina commented 3 years ago

Would you like to send a PR @robertherber?

robertherber commented 3 years ago

@mcollina I'd love to - but not sure I have the time to dig into it right now.. =/

nghiepdev commented 3 years ago

Any updates on this?

mcollina commented 3 years ago

This requires work :(. Would you like to help?

igrlk commented 2 years ago

@mcollina are you still open for the PR? I started working on that so will open it some time soon!

mcollina commented 2 years ago

@igrlk what's the status of the spec for these?

igrlk commented 2 years ago

Hey @mcollina. I've just made a PR with the implementation where I also tried to list all the things I found that describe the current state of @defer - https://github.com/mercurius-js/mercurius/pull/898