Open RichardWarfield opened 6 years ago
I'm quite interested in that too, I would really like to add initial values in graphql-api because when linking efficiently grahpql objects/fields with sql couterparts, we need that (c.f. #182 for more precision).
In my opnion initialValue
is part of the spec of resolvers, so if we want to follow the spec, we should add that, or at least some sort of context object which is injected by a father node to its children.
As much as I like this argument workaround, I'm not sure how it extends to all the use cases of initial values in the resolvers. Besides, this workaround push the implementation farther from the spec, which I don't think is the right approach...
I'd like to help with adding GraphQL subscriptions support to this package. I have started porting the subscriptions-transport-ws package for subscriptions over WebSockets to Haskell here. There's a sample application and GraphiQL frontend for testing.
The below discussion is about the issues encountered in creating an implementation of subscriptions with
graphql-api
. TL;DR: I can't quite follow the spec on subscription execution due to the lack of aninitialValue
concept ingraphql-api
resolvers/handlers. I've implemented a workaround and would like to get feedback from thegraphql-api
authors/community.For graphql-api to support subscriptions in terms of syntax and validation, the changes are pretty trivial and obvious (see my fork).
Execution is tricker. Unlike for queries or mutations, the section in the spec on executing subscriptions is pretty long and detailed. For reasons explained below, I don't believe it is possible to follow the spec's execution methodology closely in graphql-api (at least without significant and annoying changes).
To summarize my understanding of the spec (and simplifying greatly), a subscription should be executed as follows:
In my example app, the source stream is just a clock that pushes the current time to the stream each second. Under the spec's methodolgy, each timestamp would get passed to ExecuteSelectionSet as the initial value, which in turn calls the field resolvers which also receive the initial value.
In
graphql-api
there isn't the concept of an initial value passed to resolvers/handlers. I suppose this could be added but it would break a lot of stuff and be ugly.The workaround I've used in the sample app is, instead of passing the source event as an initialValue (which doesn't exist in graphql-api), I instead pass it as an Argument. So my root schema looks like:
Then when a user issues a subscription) {...} }, which gets executed once for each source event (i.e. the time stamp).
subscription sub { now { ... } }
, it is converted into a query like `{ now(sourceEvent:I'm not sure whether this is the best approach to take for executing subscriptions. I can think of several issues off the top of my head The extra argument is ugly, and end users might see the "wrong" schema -- though some type synonyms /
newtypes
and simple schema transformations could fix these problems.