-
Notifications
You must be signed in to change notification settings - Fork 434
GraphQL-WS crate and Warp subscriptions update #721
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
Conversation
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.
This looks great!
}, | ||
)) | ||
.map(move |ws: warp::ws::Ws| { | ||
let root_node = root_node.clone(); |
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.
Would it make sense to put this on the route?
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.
This seemed simpler to me, but if someone with more Warp expertise tells me it would be better for whatever reason (demonstration purposes?), I'm happy to change it.
Thanks for this! Will look in-depth in a bit. One thing I am worried about is you can use subscriptions without So I want to make sure we have "open-ended" subscription support for people to roll their own protocol as well as practical opinionated support like |
Yep, I'm definitely not reducing functionality of the general purpose crates. You can still use |
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.
This is great, just some small comments.
I invited you as a maintainer as this is high-quality work (thank you! Love the tests) and I don't personally use subscriptions. I don't want to be a blocker for you making improvements here!
.boxed(); | ||
s = s | ||
.chain(stream::unfold((), move |_| async move { | ||
tokio::time::delay_for(keep_alive_interval).await; |
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.
It is a huge bummer to use tokio just for a delay...AFAICT everything else is executor-agnostic. Is there a generic delay that only depends on futures
?
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.
Agreed. I looked for a bit before adding the tokio dependency, but couldn't find anything. :(
async fn start(id: String, params: ExecutionParams<S>) -> BoxStream<'static, Reaction<S>> { | ||
// TODO: This could be made more efficient if juniper exposed functionality to allow us to | ||
// parse and validate the query, determine whether it's a subscription, and then execute | ||
// it. For now, the query gets parsed and validated twice. |
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.
Can you file an issue to track?
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.
Sure thing. Will do once merged.
stream::iter(vec![ | ||
Reaction::ServerMessage(ServerMessage::Error { | ||
id: id.clone(), | ||
payload: GraphQLError::ValidationError(vec![ |
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.
Should we add a new error type here? I guess it is technically validation...
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.
🤷 I don't really feel strongly either way.
@LegNeato mind taking another look over the last few commits? I added what appeared necessary to make CI happy, but I'm not super confident as I don't know much about the repo's release process. If everything looks good to you, I think this can be merged now. |
Looks great! 🚀 🍾 |
@ccbrown does this GraphQL over WebSocket protocol implementation support queries and mutations too? Or just subscriptions? |
It supports queries and mutations too. |
This add a new crate:
juniper_graphql_ws
. This crate implements the Apollo graphql-ws protocol.This is a replacement for the implementation that was previously in
juniper_warp
. A few of the differences:Simplifies(Edit: This was merged separately.)SubscriptionConnection
. There is a dedicated PR for this here: Simplify SubscriptionConnection #719. This can be reviewed separately, or that PR can be closed and everything can just be reviewed at once.juniper_subscriptions::whole_responses_stream
. This and the first bullet are the only changes outside of the new crate,juniper_warp::subscriptions
mod, and thewarp_subscriptions
example.format!
.Sink + Stream
and there are proper message types, writing unit tests is a breeze.I suspect there are more. The previous implementation was really rough. But on to the usage.
Usage
I'm just going to copy a unit test:
It couldn't really be any easier.
The second argument to
Connection::new
is generic. Instead ofConnectionConfig
, you can provide a closure:This allows you to defer the configuration until you receive the "connection_init" parameters. Any error returned by this closure is sent back the client.
The entire
juniper_warp::subscriptions
module is now just a few lines to compose the sinks and streams:So adding support for the other frameworks should be pretty trivial now and they can all share one implementation.
Related Issues
Depends on / includes Simplify SubscriptionConnection #719
Obsoletes Unsubscribe fix #717
Obsoletes Implementation of some websocket utilities in juniper_subscriptions #617
Obsoletes Add subscriptions connection_init behaviour #597
Simplifies Impl subscriptions for juniper_actix #716
Simplifies Implement Subscriptions for juniper-actix #649
Closes juniper_warp::subscriptions rewrite wishlist #709