Listen to CloseNotifier in stream handler.

Problem:

context.Stream() already listens to the closeNotifier, which gives the impression that context.Stream() will return as soon as a client disconnects.  Unfortunately, it doesn't!

This example code furthers the impression with the defer closeListener(roomid, listener) which one would expect to be called when a client navigates away, which is not the case.  In fact, it's only called on the next message that's sent to the room after said client exits. 

This is because c.SSEvent("message", <-listener) blocks indefinitely until a message comes in, so will not return and yield to c.Stream()'s select that catches the closeNotify.  This means that if a client navigates away, the server never notices and cleans up.

Fix: Also listen to CloseNotifier inside stream handler.  This causes the step() function to return immediately when the client goes away and allows the cleanup to run.  Updating this example should make it more clear, I think!
This commit is contained in:
spynup 2015-07-22 12:20:47 -07:00
parent fd5d4294a5
commit ecd836af75

View File

@ -25,9 +25,15 @@ func stream(c *gin.Context) {
listener := openListener(roomid)
defer closeListener(roomid, listener)
clientGone := c.Writer.CloseNotify()
c.Stream(func(w io.Writer) bool {
c.SSEvent("message", <-listener)
return true
select {
case <-clientGone:
return false
case message := <-listener:
c.SSEvent("message", message)
return true
}
})
}