-
Notifications
You must be signed in to change notification settings - Fork 491
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
Support subscriptions #203
Support subscriptions #203
Conversation
// Send response within timeout | ||
// TODO: maybe block until sent? | ||
select { | ||
case <-subCtx.Done(): |
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 you send a timeout error here?
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.
Don't believe it would make sense to try and send a timeout error since we've time'd out waiting to send an actual response. But I do think maybe this should be checking against ctx.Done()
instead. Thoughts?
subscription_test.go
Outdated
import ( | ||
"context" | ||
"encoding/json" | ||
stdErrors "errors" |
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'd personally add an alias to the other "errors"
package and leave the standard lib one as is.
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.
done
subscription_test.go
Outdated
helloSaid { | ||
msg | ||
} | ||
} |
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.
Please, fix indentation above.
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.
done
return r.msg, r.err | ||
} | ||
|
||
func closedUpstream(rr ...*helloSaidEventResolver) <-chan *helloSaidEventResolver { |
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 this be named closedChannel
instead? For a moment, I got confused about the meaning of upstream
here.
subscription_test.go
Outdated
subscription onHelloSaid { | ||
helloSaid { | ||
msg | ||
} |
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.
Fix indentation.
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.
done
subscription_test.go
Outdated
subscription onHelloSaid { | ||
helloSaid { | ||
msg | ||
} |
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.
Fix indentation.
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.
done
subscription_test.go
Outdated
|
||
type Query { | ||
hello: String! | ||
} |
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.
Fix indentation.
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.
done
subscription_test.go
Outdated
const schema = ` | ||
schema { | ||
subscription: Subscription, | ||
query: Query |
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.
Fix indentation.
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.
done
This is a good start! Thank you @matiasanaya! |
lgtm |
08079d8
to
a2b77e9
Compare
Hello everyone who are pursuing the endeavor of implementing subscriptions. How it is going recently? Do you need assistance? |
We strongly need subscriptions aswell, we would be glad to help if any work remains before merging this PR! |
@Xeizzen @tsauvajon - I've written a new transport library that aligns with this library and updated the subscription example server with a more robust implementation. If you are keen, please have a look at those projects, try them out and contribute :) |
LGTM, I tried it in our project and it works as planned. EDIT: we implemented some features with this and it's perfect for our needs. Subscriptions work as planned. We love the use of channels for this. |
The thing I don't really understand is select {
case r.pointScoredEvents <- e:
case <-time.After(1 * time.Second):
} Why use a |
The above select statement will block until one of these happen:
In other words - wait for someone to receive your message (i.e. |
We also really need subscriptions. I was wondering how close this is to being checked in. =) |
@ande8133 check @matiasanaya 's link. Subscriptions work for me following his example. I just had to add CORS and return 200 on OPTIONS (for preflight requests). |
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've got it working using this PR too. We should definitely merge this. It's a very good starting point.
Is there a reason why this is not yet merged? |
I was wondering the same... |
@tonyghita @neelance please consider spending little of your time as it been the most requested feature and many claim works well. thank you. |
IMHO, It seems PRs are not appreciated. |
@smithaitufe @neelance commented here as he don't have the bandwidth for some time. I wish more capable maintainers are identified :-( . |
Is there no one else maintaining this project? Is it just @neelance ? |
I am not maintaining this project any more, since I'm currently (unfortunately) not working on any project that uses GraphQL. Therefore I'm a bit detached from the GraphQL ecosystem atm and someone else would probably do a better job at maintaining this project. @tonyghita already volunteered, but we can add another helping hand if someone wants to take the job. ;-) |
I would like to volunteer. I have been following the project very carefully and my team has been using it in production for more than 1.5 years. We are interested in subscriptions but also extensions and other GraphQL features. @matiasanaya (the author of this PR) is also from my team and I peer-tested his work long time ago. I'm a little disappointed that there hasn't been much activity lately. |
I'll be happy to, although since I've not contributed to this project before, I don't know if I am the best person to do it. However, I am working heavily with something involving GraphQL, and will be for a while. |
Adding this project to the #gfrs list in the gophers Slack might be a good idea. This way it can be trully community managed! |
I agree @pavelnikolov |
I'd like to have a single primary maintainer for the project. The primary maintainer can add secondary maintainers if desired. @pavelnikolov Using it for 1.5 years sounds like a good qualification. :) @tonyghita Would it be okay with you to make @pavelnikolov the primary maintainer? |
I think this would be great. |
Awesome Library kudos and thanks to the new maintainers @pavelnikolov and @tonyghita |
Thank you for trusting in me! It is an awesome privilege and I will take this responsibility seriously. |
As I read about websocket transport I'd like to ask this question: will the library remain transport-layer agnostic? Will we be able to use graphql-go with subscriptions support on top of any custom transport layer? I'm worried because we're using a home-grown websocket abstraction library called webwire together with graph-gophers/graphql-go and we currently implemented subscriptions without GraphQL support just by using webwire server-side signals and regular mutations |
@romshark I think that the library has to remain transport agnostic and as minimalistic as possible! The WS transport will be added as a separate repository under |
@matiasanaya does this use one websocket for all the subscriptions that the client has, or is it multiple connections? I know that with apollo it's possbile to send queries and mutations via websocket as well. |
@lindroth the library itself is transport agnostic. The subscriptions updates are sent over Go channel. It's up to the user of the library to decide how to handle it. There is a reference websocket implementation that @matiasanaya worked on and send a PR graph-gophers/graphql-transport-ws#1 |
@lindroth if you end up using graph-gophers/graphql-transport-ws (once it's merged), one websocket can be used to handle all subscriptions, queries and mutations. It's based on the apollo implementation. In the end though it's going to be up to the client you use. |
🎉 |
Awesome work on this!
@matiasanaya Trying to do exactly what you're suggesting here - use websockets for not just subscriptions but querying as well (to lower the number of http requests from the browser), but the implementation seems to explicitly prevent that. Lines 48 to 50 in 940d2b0
I'm using apollo-link-ws on the browser side. Am I missing something? |
@hampusohlsson Thanks for your comment. I haven't used |
@hampusohlsson I believe you are right and that I've, at some point, sneaked in this limitation. Care to raise a separate issue so we can track the work to support queries and mutations through subscriptions? |
No problem! Opened an issue here #286 |
…ptions Support subscriptions
This addresses the subscription part of #15.
Please look through
subscription_test.go
which has an example subscription resolver implemented.I've left
// TODO: ...
markers where I feel the implementation could be improved, though not sure how.Missing from this PR is tracing for the execution of each query.
I've put together a graphQL server that supports subscriptions as a proof of concept based on these changes (though it might be out of sync since this PR is changing)