Repository navigation
fix(sdk): replace a first peer connection that has not connected after 3 s - #786
Draft
realhasanshoaib wants to merge 5 commits into
Draft
realhasanshoaib wants to merge 5 commits into
realhasanshoaib wants to merge 5 commits into
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
…r 3 s A first ICE negotiation that gets no STUN reply (about 1% of new Cloudflare sessions) stayed silent for about 15 s, until Chrome reported failed. The client now gives a never-connected peer connection 3 s after its answer is applied, then replaces it with a new grant, session and peer connection, at most twice, with a 0 s then 1 s wait. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…dget The receive path replaced a stuck connection once, then let the second timeout escape into the 15 s pull deferral. Publish and receive now share one loop, retryOnReplacedConnection, that replaces and retries while the failure may still be replaced. Splitting replaceMediaConnectionForRecovery into small helpers also clears the fallow complexity finding. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ent grant The grant moved participants.media_connection_id without touching the registry, so the old connection's publication stayed enabled in the registry and in Sync until a later read retired it. Listeners pulled it on a session the client had already abandoned. Reading Latest after the binding retires it and appends the observation that Sync is notified about. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The 3 s deadline replaced slow but healthy connections, including ones whose ICE had already connected. The deadline is now 5 s, and a connection whose ICE is connected, or checking with a server response, keeps waiting. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
realhasanshoaib
force-pushed
the
fix/first-connect-ice-deadline
branch
from
November 1, 2026 16:40
61d3ffd to
067a02e
Compare
… live When the extended wait ends on a still-unconnected first peer it now raises the retryable first-connect failure tied to that peer, so the replacement budget applies instead of a non-retryable media_failed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
realhasanshoaib
marked this pull request as draft
November 1, 2026 18:54
Contributor
Author
|
Parking this as a draft: the impaired-network rig doesn't support merging it. Run 4: 30 rooms per arm, on the 067a02e server, interleaved on 2 machines. Intervals are 95% bootstrap intervals.
|
This branch has not been deployed
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.
About 1% of first connections to a new Cloudflare session never get a STUN reply, and Chrome reports
failedonly after about 15 s. A listener hears nothing for that long and a speaker's join fails. A first version of this fix replaced at 3 s. Rig runs (24 rooms per arm) showed that was worse: 6.9% of listeners heard after more than 5 s, against 4.7% without it. Replacing was slower than waiting in 14 of 17 cases, and in 5 the old connection had already reached ICE connected.Fix
FIRST_CONNECT_DEADLINE_MS). Only 6 of 383 first connections took longer, so a healthy connection almost never reaches it. At the deadline the client checks the real state (iceIsProgressing). If ICE is connected, or checking with at least one server response, it keeps waiting out the old 8 s window. Only a stuck connection is replaced. If the extended wait ends with the connection still not live, it counts as stuck too and takes the same replacement path.#retryOnReplacedConnection, at most two replacements, backoff 0 s then 1 s.ActiveAuthorizer.BindParticipantMediaConnectionandCompleteParticipantMediaRefresh(apps/api/internal/accessgrants/active.go) now readmediapublications.Service.Latestright after the new connection is bound.Latestretires every publication whose connection no longer matches the participant and appends the observation, which fires thechalk_media_publicationsNOTIFY that Sync reconciles on.What changed
Changed: SDK first-connect deadline and pre-replacement state check; API access grant now retires and announces the old connection's publication.
Untouched: the replacement loop,
disconnectedwait, the Sync service, the API contract.Why listeners pulled the old publication: The access grant moved
participants.media_connection_idand recorded nothing in the publication registry. The old publication stayed enabled in the registry and in Sync's projection until something readLatest(retirement is lazy,service.go:173-228) or the 15 s Sync timer fired. Listeners got it fromsfu_signaling.go:532or Sync, pulled it on the abandoned session, and heard only after 5 to 9 s.If the announcement fails, the grant still succeeds and logs a warning, because the binding is committed and the next read retires the publication.
Proof
active_test.goasserts that a bind and a completed refresh each read the registry once after the binding, that a failed binding does not, and that a failed read does not fail the grant. It failed to build before the change (NewActiveAuthorizertook no publication reader).go testpasses foraccessgrants,httpapi,mediapublications.media_failed). Full SDK suite 1520 passed, 2 expected fail; lint and fallow clean.adapters/postgresintegration tests (no local database; the package compiles and vets).Known and not changed here: a concurrent registry read during a refresh's temporary
replacement:binding can retire a live publication if the grant then fails. That window exists on master (Latestis unchanged by this PR); follow-up in #787.Revert with a plain revert of the two commits.
Created with Claude Sonnet 5.5 in Claude Code.
🤖 Generated with Claude Code