-
Notifications
You must be signed in to change notification settings - Fork 528
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
@defer directive support #559
Conversation
This could be a lifesaver for my project. Thanks a lot @bernardd for making it happen. |
@benwilson512 So I was thinking about our Slack discussion re continuation vs message passing. I now have it a bit clearer in my head why I went down the road I did: While calls can be made concurrent with multiple HTTP requests, that's not the way things are usually done with websockets (which is the connection style we will generally be dealing with here). My whole intention with this system was to allow for the client to continue to make and receive other requests while the DB (or whatever other backend) is churning away on a more expensive request. If we make the process block waiting for that request, which is what the continuation style would do (unless I misunderstand) then we're automatically precluded from handling anything else on the same websocket connection. |
761994b
to
391d696
Compare
So I think I've added everything I want to for now. I'm happy to for this to be reviewed with a view to merging what's there. |
f0b8654
to
2a13b40
Compare
def unregister(registry, key) when is_atom(registry) do | ||
self = self() | ||
@spec unregister(registry, key, pid) :: :ok | ||
def unregister(registry, key, pid \\ self()) when is_atom(registry) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately this can't work for two reasons. 1) The registry here is really just a copy of the Elixir 1.5 registry module, which we included in the code base simply to support Elixir 1.4. Elixir 1.4 didn't have the match_delete function.
- The reason that the Elixir Registry module doesn't support passing in the pid is that unless the process is unsubscribing itself there are race conditions and the function is no longer safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dangit. Okay, I'll figure out something else.
Let me see if I understand what you're saying. Given the following doc:
What I was suggesting is that pass 1 on the document would execute essentially:
and then when it was done push the result to the user. Then it would run the remaining blueprint which was:
And push that. Now for a slightly different doc:
Is your concern that the slowness of |
No, and sorry - I may be totally misunderstanding the internals here, but my concern is that if the user pushes another, unrelated query down the websocket, that second query will have to wait for all the pending |
Ah. Great question. Let's consider those two cases (queries / mutation vs subscriptions) separately cause they have different execution models. SubscriptionsLet's start with subscriptions. Subscriptions are largely unaffected by this because subscription resolution does not happen inside the subscriber process, but rather inside the trigger process. If clients A and B submit Then if C pushes a mutation, all relevant subscriptions are retrieved from the store and executed as a batch inside C's process, and then the results are pushed to A and B. The execution time of A and B's subscriptions does delay C's response, but this is an intentional design decision to create back pressure. If C's mutations are triggering a lot of work on the server then C needs to bear some of the cost of that work lest they overload the server. Queries / MutationsAt the moment if you submit a query via websocket If concurrent document execution is the desired feature, I think it may be best to aim for that as its own feature within Absinthe.Phoenix, since this would solve that problem for not just |
Okay, great, thanks - that all makes sense (except now I'm going to have to learn the guts of |
599269c
to
21abecf
Compare
Okay, take 2 reworked with continuation-style resolution. Enjoy :) |
Ping @benwilson512 Sorry to keep bugging you, but would it be possible to get some feedback on this? I'm not so worried about urgently merging it, but I have a couple of other use cases that would also benefit greatly from being able to use continuations like this and it'd be really good to know if it's likely to be generally acceptable in this form (even if there's issues with this specific PR). In particular, I'd like your opinion on the change to the |
Hey @bernardd I like the I don't mind additional phases, since those could be added by anybody, but I was hoping there was a way to do this without adding a clause to the resolution phase. My thought would be that the schema author may need to add defer middleware to fields they want to allow being deferred, and that deferment middleware would be able to handle that instead of a dedicated phase. One thing I wonder on the continuation struct: I wonder if it makes sense for it to include the pipeline that is necessary to do the continuing. |
Thanks for taking a look :)
Great, because I want to use that for another thing too :) So I'll assume it's acceptable and look at making
It's probably an option; I'd need to look at it. The reason I didn't go down that road (and am still a bit disinclined to) was that, at least as far as the (very few) published details of
At a quick glance, it looks like it might be possible to simply insert an extra phase before
Quite probably. I'll take a look at that. |
@bernardd OK, I see what you mean about whether we should require schema authors to annotate this stuff or not. The main thrust of my point though was that I'm hoping we can avoid |
7e9c4a6
to
1e559da
Compare
Okie dokes, try this version on for size. I've managed to reduce the modifications to existing code pretty substantially. Apart from the addition of continuations, the only change of any note is the addition of a Aside from those changes, the rest of the functionality is implemented by two extra phases and one new middleware. |
b7a8cf8
to
ee4ef2d
Compare
@benwilson512 any chance to review and merge this PR ? It would be awesome to add support for |
@tlvenn the plan at the moment is for me to finish the initial schema rework and then merge this in so we can include it in the 1.5 release. We should be days away from this. |
ee4ef2d
to
8f0f83c
Compare
@benwilson512 I took the liberty of rebasing this against |
8f0f83c
to
c812060
Compare
d41d0a2
to
8ee3eb5
Compare
8ee3eb5
to
2afe7be
Compare
2afe7be
to
9c44a28
Compare
9c44a28
to
1a57e68
Compare
1a57e68
to
a81c977
Compare
a81c977
to
b872bf7
Compare
Hi Guys, sorry to be a nag, but is it still happening in absinthe-1.5 ? |
It is now targeted for 1.6 (See the milestone). |
b872bf7
to
867b523
Compare
867b523
to
7077d59
Compare
FYI this is getting picked up by the GraphQL working group. It looks like it's going to make it into the GraphQL spec eventually, so we'll definitely want to make sure we implement it according to where the spec evolves... https://github.com/graphql/graphql-spec/blob/master/rfcs/DeferStream.md |
7077d59
to
8a8afc1
Compare
8a8afc1
to
ab1bbe8
Compare
Any news on this one? |
This will be revisited after the Absinthe 1.5 release later today. |
Also, the GraphQL spec for this is still being discussed, I'd suggest watching the RFC document I linked above... |
I think the right call in this case is to close the PR and await clarity from the spec. |
I've been working on an implementation of the
@defer
directive (following up on this post: https://elixirforum.com/t/adding-defer-and-stream-to-absinthe/14546), and I'd appreciate it if you guys had time to give it a once-over just to make sure I'm not approaching it in an egregiously horrible way.What's working so far:
What still needs to be done: