I've just completed implementation of the three new directives mentioned in the GraphQL Futures talk in GraphQL-Go: https://gist.github.com/paralin/f6891bd30eb96e91fba628096af3278c
I now need to enable Apollo-Client to understand these responses.
@stream
, @defer
, or @live
can be sent over a streaming channel in the same way. If a query does not require returning data at a later time, the server will just immediately close the channel after returning the initial result.["regions", 0, "status"]
and comes in in extensions.path
.These features are obviously experimental, but I've been able to build a real proof of concept of the server end of this in just a couple of days. I'm interested to now get it working properly with Apollo.
I think this is a great idea. One thing we've run into with subscriptions in Apollo is how the developer manages the state of queries - how do you choose to unsubscribe from a query, for example? What if the server disconnects while you are looking at a @live
query?
It shouldn't be too different from what we have already since the watchQuery
API supports multiple results, but there might be some edge cases once there is state on the network transport.
Curious what @helfer thinks.
Internally I would try to merge the query together with other similar queries. So, if there were 2 of the exact same live query going on, only send one to the server (I think partial support for this is in place).
The same goes if a query is a subset of another query, just merge them together when sending to the server.
We could even get clever and send one query, with an @defer
on everything that multiple queries share (i.e, one query requires it to be completed, but another does not, move the logic to determine when the query is complete to be returned to the caller to Apollo)
Finally, when nobody cares about some data anymore, we can instruct the network interface to terminate that ongoing query. In Go this is already implemented, in that we can cancel the containing Context for the request, which will immediately terminate all running resolvers and operations.
@paralin is your project on github? would be great to have a look
http://GitHub.com/paralin/graphql-go
Feat-defer branch.
Oh, and I plan to start prototyping supporting it in Apollo today but I haven't started yet
I feel like the best way to go would be to do most of the fancy stuff about query merging etc on the server, and have the client send queries in a similar way to how it does now. Is there any advantage to doing it on the client?
Only if your requests are getting load balanced without sticky sessions. It's a valid approach to open one web socket per query now, or use long lived HTTP requests.
Oh, the approach I was thinking of is to use one web socket, and send multiple queries over that while the connection is open. That's what we currently do with GraphQL subscriptions which is working quite well for some people in production already.
That's how I'm doing it in my app, I'm just saying some people might do it differently for scaling reasons.
@paralin That looks pretty interesting so far. I think the only modifications necessary to support this kind of thing with watchQuery
would be to change the interface of the NetworkInterface from a promise to an observable. @DxCx was really interested in doing that a while back, but I guess he never got around to it. Once that's done, all we'd have to do is modify a few lines in the core to allow patching of results in the store.
I think those changes will get us about 90% of the way there, but then there are a couple of things that we probably need to rethink, for example what new networkStatuses to introduce (maybe incomplete
for @deferred
?) and how to make this work with queries that do not want partial data. And then there are all the questions to consider, like what happens when the server goes down. What happens when dependent patches arrive out of order etc. An experimental system can just crash and burn in this case, but for a production library that's not a viable option.
That said, I'm sure we can figure out a solution for all these challenges as they come up!
hi @helfer i'm still into that ;), just don't have the time to do it myself...
will get to it eventually probably if nobody else will do it..
I'm abit more concern about graphql-server which i see people are not investing into almost at all.
so i'll probably have to finish couple of stuff on graphql-server before getting into this...
On the server these @live queries could be observables rather than promises. If they were ReplaySubjects then the server would give out the last obtained value for queries which are already subscribed to.
Making the query and subscription effectively the same operation means you don't miss updates in between querying and subscribing.
A fully live client would only retain data it was currently subscribed to. So if data is to be cached it would also remain subscribed to. On unsubscription it would be removed from the store.
@gilesbradshaw i've implemented the graphql execution engine using rxjs just for that.
(package is called graphql-rxjs) at the moment only subscriptions are supported but i'm planing to support directives the same way.
for more info you can reference https://github.com/apollostack/graphql-subscriptions/pull/30
nice thinking ;)
@gilesbradshaw In the Go implementation we can return a channel to represent live data. That channel closing indicates there are no further updates to the Live state. Similar to ReplaySubject, it's simple in Go to take a channel of values for a field, and push those into another channel - thus deduplicating the requests.
I'd say if anything it's a "nice to have" thing to have the GraphQL engine automatically do the batching. And it's also something that isn't relevant to apollo-client, I agree.
With my @live
stuff the query and subscription are done in the same operation and I agree that that's definitely a superior approach to subscription
which seems unnecessarily limited and simple.
@DxCx How far are you on supporting directives? I'd be happy to work with you on this.
Why do we even need the concept of queries anymore? Other than on the client side?
It seems to me with a connection between the server and the client, we can just keep one single query object synced between the client and server, and allow the server to push any changes to that giant query object back to the client over time.
I like this model a lot because it would completely eliminate all of the complexity around query batching, merging, etc.
So we would still have the concept of "queries", just we would query against the local store which would act like a state machine - Query -> add any missing fields, +1 ref count for all referenced fields, upgrade any directives as necessary, transmit change to server, server evaluates what changed between old query object and new and kicks off any new resolvers and cancels anything it doesn't need anymore.
Implementing my last comment here:
Any progress on supporting @defer
on apollo? :smile:
@paralin i havn't seen your message..
if you want to dicuess you are welcome to DirectMessage me @ slack (hagaico) :)
This issue has been automatically closed because it has not had recent activity after being marked as stale. If you belive this issue is still a problem or should be reopened, please reopen it! Thank you for your contributions to Apollo Client!
Any news on this defer
functionnality ?
I think this is a good thing to reopen - part of the work for #1941 (Apollo Client 2.0) is supporting multiple results for the same query, which will make supporting @live
and @defer
pretty easy!
This issue has been automatically marked as stale becuase it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions to Apollo Client!
Yay, auto-closing issues
I'm trying to get a holistic view of where @defer/@live/@stream
is being implemented for experimental purposes.
Now that #1941 is merged is it the right time to implement support here? Can this work be used in conjunction with https://github.com/DxCx/graphql-rxjs? Is there work that a new contributor could do to help push this along?
@azz I think @DxCx has something working already, probably the right person to talk to!
@paralin lol we misconfigured stale bot. It's supposed to ignore issues with discussion
label:
Should be safe now!
Hey @azz
Feel free to catch me on slack (hagaico) if you want to hear where things stands :)
The basic level of this is supported in the core with 2.0 but there needs to be a lot more work around standards for handling partial data and response shapes for these directives 馃憤
Leaving this issue open until we get to that. If any contributor wants to help (along with @DxCx) please reach out in slack or here!
@DxCx Can you provide us an example for @defer ? I'm using query batching, but one request is really slow.
Error: GraphQL error: Unknown directive "defer".
thanks
hey @goldo
you will need to work with websocket interface in order to make defer works.
here is an example repo:
https://github.com/DxCx/graphql-rxjs-websocket-example
Ok, so I already detailed most of this here. The caching policy seems broken to me with regards to @defer
. There are two main problems:
@defer
is not a known directive (neither is @live
)@defer
returns partial results that do not contain all of the expected properties, which breaks on the infamous try/catch.To help provide a more clear separation between feature requests / discussions and bugs, and to help clean up the feature request / discussion backlog, Apollo Client feature requests / discussions are now being managed under the https://github.com/apollographql/apollo-feature-requests repository.
Migrated to: https://github.com/apollographql/apollo-feature-requests/issues/3
Just to add - @defer
support is here now: https://blog.apollographql.com/introducing-defer-in-apollo-server-f6797c4e9d6e
Most helpful comment
Any progress on supporting
@defer
on apollo? :smile: