-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add subscriptions.md
recipe to docs
#2346
Add subscriptions.md
recipe to docs
#2346
Conversation
This looks great. Sorry for the delay! I was trying to figure out some way to scrape this and other tutorials to test that it continues to function, as we have had some problems where we don't always keep the documentation up to date. |
Thanks @StevenACoffman! I'll look into if I can write some kind of automated unit-test for the tutorial code, although I don't quite know how I'd go about testing everything at once |
I have a question. In blog posts from previous versions, I was looking at people awaiting for ctx.Done() to be invoked, but now I see the examples in the docs are awaiting the default of the select. Is there something that requires the change? |
@zdraganov |
Thanks for the quick reply! I will give you my example that we have to use the subscriptions and using func (r *subscriptionResolver) ChatMessage(ctx context.Context) (<-chan model.ChatMessage, error) {
user := utils.GetUserFromContext(ctx)
channel := r.ChatMessagesBroadcast.Subscribe(user.ID) // this returns the <-chan model.ChatMessage
go func() {
<-ctx.Done()
r.ChatMessagesBroadcast.Unsubscribe(user.ID)
}()
return channel, nil
} I have found couple of examples online following this approach, but in that case we have the control at which point to call the Unsubscribe function to properly release the subscription. If I follow the example from the docs, my implementation should be something similar to: func (r *subscriptionResolver) ChatMessage(ctx context.Context) (<-chan model.ChatMessage, error) {
user := utils.GetUserFromContext(ctx)
channel := r.ChatMessagesBroadcast.Subscribe(user.ID)
resultChannel := make(<-chan model.ChatMessage)
go func() {
for {
msg := <- channel
select {
case resultChannel <- msg:
default:
r.ChatMessagesBroadcast.Unsubscribe(user.ID)
return
}
}
}()
return resultChannel, nil
} The example above is not only looking more complex, but can lead to a blocking on For me it's even confusing that the library is going to close the returned channel and not giving you the option to release it the way you want. What do you think? Can you see in the code where actually the returned channel from the subscription is getting deleted? |
If the implementation which provides the channel / sends to it already handles safe sending your first solution is good, and yes it's cleaner. However if the send is unsafe (aka. just sending without any go func() {
<-ctx.Done()
// Imagine right here the send is happening -
// The unsubscribe has not yet happened, even though
// the context has been finished
// The send method will now panic and, if not `recover()`-ed
// it will take your entire program down.
r.ChatMessagesBroadcast.Unsubscribe(user.ID)
}() The example I wrote for the documentation is built with the |
After couple of load tests, I can confirm that you should check before sending to the channel. There is really a race condition causing send to closed channels even with the |
Actually I found one more issue with the approach in the docs. |
That's actually a good call, you're completely right on that! |
I've recently wanted to add subscriptions to my GraphQL-API and couldn't find anything in the official docs.
I think that's a shame, so I've decided to change it. 😄
This PR contains
docs/content/recipes/subscriptions.md
which in turn contains my tutorial on subscriptions.If you read this, please take some time to proof-read the document and if you find a mistake, please do a code-review with a change suggestion. I've tried proof-reading to the best of my ability, but more eyes are always better!
I have:
Added tests covering the bug / feature (see testing)Closing #953