-
Notifications
You must be signed in to change notification settings - Fork 216
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
[phantom-presence] handle stray websockets #207
Conversation
View Vercel preview at instant-www-js-socket-issues-jsv.vercel.app. |
(let [pooled (.getData message)] | ||
(try | ||
(let [payload (.getResource pooled)] | ||
(on-message {:channel (channel-wrapper channel) | ||
:data (Util/toArray payload)})) | ||
(finally (.free pooled))))) | ||
(onPong [^WebSocketChannel channel ^StreamSourceFrameChannel channel] |
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.
You may be wondering:
How does the client know to send a pong
, we did not change Reactor.
Most clients now can handle websocket pings by default. So since the server sends ping
, chrome will automatically respond with a pong.
(Tested this with chrome and expo iOS)
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.
Nice work!
@@ -548,7 +533,6 @@ | |||
:http-req http-req | |||
:ws-conn ws-conn | |||
:receive-q receive-q | |||
:ping-job (start-ping-job store-conn id) | |||
:pending-handlers pending-handlers}] | |||
(on-open store-conn socket))) | |||
:on-message (fn [{:keys [data]}] |
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 update the atomic-last-received-at
in on-message
also?
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 pushed this down to the caller of on-message, so this already happens. Took the inspiration of updating on every message from Precursor : )
This PR:
Context
Kosmik reported a curious bug: If you went offline and went back online, you would get a phantom presence object. What happened?
Bugs
The fundamental bug was this: tcp connections stayed 'active', even when we went offline.
We assumed that the underlying websocket would close when we went offline. But this is not the case. Google Chrome does not close the socket automatically when you go offline. [1]
What happens to idle TCP connections really depends on the machine [2]. Sometimes it can take minutes to close the connection.
Solutions
I did two things in this PR:
1) Client: Close previous connections when starting new ones
In Reactor, when we go back online, we run _startSocket. We used to assume that previous
_ws
would have been closed. Now no more: when we start a new socket, we'll make sure to close the previous one.2) Server: Start ping/pong
Having the client close stray connections is a good step. But it doesn't quite cover it. For example, if the user goes offline, and never goes back online, then what?
The server could keep the connection around for minutes. Here's what we do now: the server sends
ping
messages every 5 seconds. If we don't receive some message within 10 seconds, we close the connection.[1] Here's an interesting chrome bug report
[2] Interesting microsoft article hiredman shared with us
I kicked off a conversation about this on the clojurians slack