Stop losing calls to session expiry, teardown and stale devices

Featurekamo-internal
Shipped
August 26, 2026 at 2:23 AM UTC
Author
kamo
Commit
fb38c7a

Four guardrails that share two files, so they share a commit. A live call now counts as session activity. ClientActivityTracker equated presence with input events, so a member listening on a long call read as idle: the Redis TTL decayed, the expiry warning opened in a tab they were not looking at, and /logout tore down the tree holding the SIP session. Routed through the existing markNow() so logout's disable still wins — sessionMonitor's own floors (120s activity window, 60s re-extend minimum) govern the cadence, so this cannot run away. A document that dies holding a call now says so. pagehide fires a best-effort BYE — the far end previously sat on a dead leg until the registrar timed the contact out, up to ten minutes at expires:600 — and a keepalive beacon carrying member, org, provider and hadLiveSession. Nothing anywhere counted how often a teardown actually costs a call, so there was no number to weigh a bigger fix against. The beacon allow-lists its fields: no remote numbers in a pod log, and ids stay strings because they are int64. A second tab no longer rings with a dead Answer button. The VOIP STOMP topic is a broadcast, so every open document set hasIncomingCall while only the one the provider sent the INVITE to could answer. Gated on the session rather than the SDK, because with two tabs open both hold a registration. A device change reaches the call from any window. saveAVSettings dispatches a same-window CustomEvent; only useAVSettings also listened for the cross-document storage event, so every call-path consumer missed a change made elsewhere — silently, because applySinkId swallows every failure. One subscribeAVSettings now covers both halves.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing