feat(stream): say what the connection is doing, and stop leaking sessions - #1155
Conversation
…ions (#1134) Reconstructed from #1143, which could not deploy. This half carries the fixes and adds no dependency; noise cancellation and background blur are split out because their packages are what broke the deploy. **Sessions never closed because the SDK was told to wait forever.** `setDisconnectionTimeout` defaults to 0 in Stream, which means "remain in the call until the connection restores or the call is ended". A participant who shuts their laptop therefore never emits `call.session_participant_left`, and the session stays open indefinitely. That is where the 1,417 MeetingSession rows with no `endedAt` came from. Set to 90 seconds. **Every non-JOINED state rendered the same bare spinner.** A network blip, an SFU migration, a dead network and a connection the SDK had permanently given up on were indistinguishable, and the terminal ones had no way out. Each state now says what it is, and only RECONNECTING_FAILED and LEFT — the two a Call instance genuinely cannot recover from — offer a rejoin. That rejoin goes back through `/api/meetings/[id]/join`, because that route is what grants Stream membership, and restores the mic and camera to what the person had chosen rather than the call type's defaults. **Leave now renders for every state.** Gating the whole button row on `canRejoin` left someone in RECONNECTING, MIGRATING or OFFLINE on a full-screen takeover with no control at all, waiting on a reconnection that might never come. Caught in review on #1143. **A client that never arrives no longer means a permanent skeleton.** The resolution effect returns early while the video client is undefined — rightly, since the provider mounts it lazily — but it re-runs only when `client` or `callId` changes, so a client that never came left `isCallLoading` true forever with no error and no exit. Bounded at 45s, sized against the provider's own retry ladder (five attempts, `min(1000 * 2^n, 30_000)`), so it cannot fire while that is still legitimately working. **Receive-side video quality** lets a participant ask for less video than the sender is publishing, which is the single largest cost lever in this subsystem. 25 suites / 333 tests, tsc and eslint clean. No package.json change. Part of #1134
✅ Deploy Preview for familiarise ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Warning Review limit reached
Next review available in: 54 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (11)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploy green — the diagnosis is confirmedThis branch deployed successfully in 337 seconds, on the same site, same build command and same heap that failed 18 times out of 18 on #1143. The only difference between the two is the absence of Two things follow that are worth recording. Background blur is very likely shippable. The exclusions were not the fix and should not be mistaken for one. |
|




Replaces #1143, which failed to deploy 18 times out of 18 and was never merged. This is the half that carries the fixes; it adds no dependency and changes no
package.json.Part of #1134.
Why #1143 was split
Its deploys failed at the deploy stage, not the build — AWS rejected the server Lambda as oversized:
The weight is
@stream-io/audio-filters-webat 44 MB, added by that PR for Krisp noise cancellation. Separately, that package is a paid Stream add-on billed per participant-minute, which is a poor fit for a pre-MVP product — and the billing shape is awkward in its own right, because Stream meters the whole call while the feature is toggled by one participant.So the filter work is parked on
parked/stream-call-filterswith a tracking issue, and this PR carries everything that was actually broken.The fix that matters most
setDisconnectionTimeoutdefaults to 0 in Stream, which means remain in the call until the connection restores or the call is ended. A participant who shuts their laptop therefore never emitscall.session_participant_left, and the session stays open forever.That is the origin of the 1,417
MeetingSessionrows with noendedAt. Set to 90 seconds here.The rest
RECONNECTING_FAILEDandLEFT— the two aCallinstance genuinely cannot recover from — offer a rejoin, and that rejoin goes back through/api/meetings/[id]/joinbecause that route is what grants Stream membership.canRejoinleft someone inRECONNECTING,MIGRATINGorOFFLINEon a full-screen takeover with no control at all. A screen that occupies the whole viewport has to offer a way off it. Caught by review on #1143.clientorcallId. A client that never arrived leftisCallLoadingtrue forever, withpage.tsxrendering a skeleton with no error and no exit. Bounded at 45s, sized against the provider's own ladder (five attempts,min(1000 * 2^n, 30_000)) so it cannot fire while that is still working.Verification
25 suites / 333 tests pass,
tscandeslintclean. Confirmed by grep that nothing underapp/,lib/or__tests__/references either filter package, so this branch cannot reintroduce the deploy failure.The Netlify deploy on this PR is the real test of that claim, since the failure it replaces only ever appeared at deploy time.