Repository navigation
Send the fallback health check before the buffered join - #6900
Merged
SteffenDE merged 2 commits intoNov 6, 2026
Merged
Conversation
The join blocks the transport process until the channel returns, so a ping queued behind it is not answered during a slow mount. Any frame on that websocket also passes the check. Fixes phoenixframework#6770.
oliviasculley
marked this pull request as ready for review
November 6, 2026 06:06
SteffenDE
reviewed
Nov 6, 2026
SteffenDE
left a comment
Member
There was a problem hiding this comment.
Let's remove the changes to the built assets in priv and then I think we can also remove the
this.ping(rtt => {
this.log("transport", "connected to primary after", rtt)
this.primaryPassedHealthCheck = true
clearTimeout(this.fallbackTimer)
})from the existing this.fallbackRef = this.onOpen(... since we now ping twice and once should be enough :)
The open callback ping repeats the one that already goes out before the join. That ping still logs the round trip. The built files in priv/static stay out of this change.
Contributor
Author
|
Okay, I think these changes should be applied now! |
Member
|
Thank you! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6770.
Steffen, this is the change I asked about on the issue. I think there are two different waits, and this only covers one of them.
If the join reply is one big frame, the browser does not hand it to JS until the whole frame arrives. I do not see a way for phoenix.js to know that download is in progress. Making that reply smaller is what helps that case.
The other wait is before the server has sent anything. The health-check ping goes out from the open callback, and
onConnOpenhas already flushed the join.Channel.Server.join/4blocks the transport process in a receive until the mount finishes, so the ping sits there for the whole mount. We had mounts of several seconds on a socket that was fine, and no frame came back before the fallback timer gave up. The tab then storedphx:fallback:LongPolland stayed on long poll.This sends one heartbeat from
onConnOpenbeforeflushSendBuffer, and only when a fallback timer is already running. The server can answer that while the mount is still running. Any frame on that same websocket also passes the check, including the ping reply. A long-poll frame does not. If the socket opens and no frame ever arrives, the client still falls back, and it still memorizes long poll.The open callback still sends its own ping after the flush. A frame that arrived first clears that timer.
I am not sure this is the shape you want. Would a heartbeat before the join be acceptable here, or should apps keep doing this themselves?