Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: support X-GraphQL-Event-Stream header #618

Open
benjie opened this issue Mar 29, 2018 · 9 comments
Open

Proposal: support X-GraphQL-Event-Stream header #618

benjie opened this issue Mar 29, 2018 · 9 comments

Comments

@benjie
Copy link
Member

benjie commented Mar 29, 2018

Server-sent events are a perfect mechanism for informing a GraphQL client, such as graphql-playground, that the schema has been updated. They don't require the complexity of websockets, and they are uni-directional.

I'm proposing that when introspecting a GraphQL API, if the header X-GraphQL-Event-Stream is detected then GraphQL Playground should subscribe to the text/event-stream at that (relative or absolute) URL and when it receives the change event it should automatically re-introspect the GraphQL schema.

Not much code should be required to implement this, just something like:

const streamUrl = response.headers["x-graphql-event-stream"];
if (streamUrl) {
  const endpointUrl = new URL(endpoint);
  const streamUrl = new URL(streamUrl, endpointUrl);
  if (endpointUrl.host !== streamUrl.host) {
    throw new Error(
      `Stream and endpoint hosts don't match - '${streamUrl.host}' !== '${endpointUrl.host}'`
    );
  }
  const eventSource = new EventSource(streamUrl);

  eventSource.addEventListener("change", this.refreshSchema, false);
  eventSource.addEventListener("open", () => { /* ... */ }, false);
  eventSource.addEventListener("error", () => { /* ... */ }, false);
}

Would love to hear your thoughts.

@timsuchanek
Copy link
Member

This sounds good! That would also be a pretty simple first task. Are you already using the X-GraphQL-Event-Stream header somewhere else or would we introduce it for this purpose?

@benjie
Copy link
Member Author

benjie commented Apr 1, 2018

I’ve added it to PostGraphile and have an open PR with GraphiQL.app; happy to open a PR here too but it might take me a while to get around to. The code above is a tidied version of the GraphiQL.app PR.

@schickling
Copy link
Collaborator

I really like this idea and wonder whether this could also be implemented with graphql-yoga out of the box. There is currently an open PR for hot-reload support: dotansimha/graphql-yoga#190

@benjie do you have any ideas how the Playground could pick up whether the underlying GraphQL server has been restarted?

@benjie
Copy link
Member Author

benjie commented Apr 2, 2018

Would detecting the event-stream closing be sufficient?

@schickling
Copy link
Collaborator

That sounds like a reasonable solution. So once it's closed it should start pinging the endpoint again like this:

image

@benjie
Copy link
Member Author

benjie commented Apr 2, 2018

Sounds reasonable. I wrote an exponential backoff with a 30 second max cutoff (basically untested though) for GraphiQL.app:

https://github.com/benjie/graphiql-app/blob/44cfa3a52c1e547b858fcfa655ed1bee3fa7fab8/app/components/App.js#L262-L313

I was only hacking it together for my own purposes at the time; that code needs some serious refactoring.

@wmertens
Copy link

@benjie I'm working on a SSE Link for Apollo, it uses a single SSE channel for all subscriptions, using a secret token to identify the return channel without cookies. This is the first time I come across your efforts - did anything come of it?

My status: it's working in the ideal state but needs work on re-establishing subscriptions after connection loss or server restart, that kind of thing. Also, I'm trying to get it working with the Playground but hitting #1362

@benjie
Copy link
Member Author

benjie commented Jan 20, 2022

@wmertens This was intended to be a way to indicate schema changes (for hot reloading a GraphQL schema); I don't see an issue with using it also for subscriptions using a different event name though. As it is, it has been implemented in Altair (https://sirmuel.design/a-better-graphql-developer-experience-with-x-graphql-event-stream-1256aef96f24) but I've not tracked its adoption into the rest of the ecosystem. A quick search on sourcegraph.com suggests it's used in PostGraphile, @enisdenjo's graphql-sse, and Altair but no other hits.

@enisdenjo
Copy link
Member

enisdenjo commented Jan 20, 2022

graphql-sse does not depend on the X-GraphQL-Event-Stream header in any way. But it could be used for discovery indicating to the client that there's a SSE endpoint available.

Following my brief investigations, trying to integrate graphql-sse in PostGraphile, running both the schema update stream and GraphQL over Server-Sent Events protocol on the same route is no problem at all. In PostGraphile's case, a GET text/event-stream request without any query parameters is considered a schema update subscription; while on the other hand, the SSE protocol needs the GraphQL execution parameters - either in the query params for GETs or in the body for POSTs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants