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

[RFC] Executor Semantics for Subscriptions #224

Closed
arunoda opened this issue Nov 10, 2015 · 3 comments
Closed

[RFC] Executor Semantics for Subscriptions #224

arunoda opened this issue Nov 10, 2015 · 3 comments

Comments

@arunoda
Copy link

arunoda commented Nov 10, 2015

This is a continuation of the discussion carried over #189 and #subscription channel of Slack.

Currently there is not details into how subscription field should work. There were some ideas and I'll try to list them over here.

Option 1 - Rerun the subscription field for each event

In this case, this is exactly just like a mutation and for some event, we run the GraphQL executor and get the result. Then we can send it to the our socket layer.

This is the simplest approach to do it. @eyston did some experiments on this.
See: https://github.com/eyston/graphql-todo-subscriptions

As dan schafer mentioned, this is the way they do subscriptions at Facebook. So, it seems like very well scalable solution.

Option 2 - Passing a observable

Other way is to pass a observable to executor. It could be a NodeJS stream. @jimmy_jia metioned this approach on slack and it. This adds some more liabilities to the executor. some of them are:

  • Provide a public API to get events where we can send to the client
  • Watch the steam and handle the end event
  • Once the subscription started, we may need to send something right away to as the result. Like a subscription id. So, there is a question like who is going to responsible for that. GraphQL or the developer?

How to unsubscribe?

I have a question about the way we do stop subscriptions. This is related to both above options. But we are going with option1, we should handle it outside of the executor anyway.

So, with option2, are we going to add a way to executor by introducing a new type of field?

All of these have pros and cons. I'm looking for some ideas on how Facebook handling these. If so, there might be a good reason.
I hope something similar subscription system will be used at some other companies. Looking forward for comments.

cc @skevy

@aihornmac
Copy link

aihornmac commented Sep 1, 2016

I have been thinking about subscription for a long time, and I think we can run a subscribe function defined along with resolve function like this:

subscribe(node: Node, args, ctx, info) {
  // do sth...
  return (actions: Actions, source, oldSource) => {
    // rerun some actions and update data
  }
}
type Node = {
  onClose: (fn: Function) => void,
  error: (err: mixed) => void
}

where actions could be different according to type:

type Path = number|string|Array<number>;

type Actions = ActionsForGraphQLList | ActionsForGraphQLOtherTypes;

type ActionsForGraphQLList = {
  insert: (path: Path, source: mixed) => void,
  update: (path: Path, source: mixed, oldSource?: mixed) => void,
  delete: (path: Path) => void,
  hold: Function,
  flush: Function
}

type ActionsForGraphQLOtherTypes = {
  resolve: (source: mixed, oldSource?: mixed) => void
}

Since GraphQLList can be used to form multi-dimensional array, so type Path could be number(for 1d), string(e.g. '0.1.3'), array(e.g. [1, 2, 3]).

This model is designed for nested subscription unlike #189.

@sibelius
Copy link

is this still relevant?

the GraphQL Subscriptions RFC is merged graphql/graphql-spec#267

@IvanGoncharov
Copy link
Member

@sibelius You absolutely right 👍
It added both into the specification and graphql-js, see #846

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

No branches or pull requests

4 participants