diff --git a/browsers/live-view.mdx b/browsers/live-view.mdx index d520bd98..921bb746 100644 --- a/browsers/live-view.mdx +++ b/browsers/live-view.mdx @@ -107,10 +107,10 @@ Both terminal events carry the same `reason`, so branch on it instead of matchin | `reason` | Meaning | | --- | --- | -| `transport` | the socket never opened inside its bound, or closed before signaling | +| `transport` | the socket never opened inside its bound, or closed at any point before the connect succeeded | | `signaling` | the socket opened but no offer arrived inside its bound | -| `media` | a peer exists but ICE never reached `checking` inside its bound | -| `peer` | peer construction or the remote offer threw | +| `media` | a peer exists but ICE never reached `connected` or `completed` inside its bound — this covers a peer that stalls after `checking` | +| `peer` | peer construction or the remote offer threw, ICE reached `failed` or `closed`, or the data channel closed before the connect succeeded | | `unsupported` | the browser has no `RTCPeerConnection` | | `server` | the server closed the connect | @@ -130,7 +130,7 @@ Both terminal events carry the same `reason`, so branch on it instead of matchin ### Detecting a viewer that never starts -Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived: +Gate on `KERNEL_PLAYING`. It fires only once frames actually arrive, so it is the signal that distinguishes a working viewer from one that is still connecting or has silently failed. The terminal events below tell you when the client has stopped trying. Start a timer when you mount the iframe and remount if `KERNEL_PLAYING` has not arrived. The timer has to outlast the client's connect bounds, which run in sequence — transport, then signaling, then media — and sum to 48s by default. If you wait less than that, you'll tear the frame down before it can report a stage that stalled late. The timer also covers loading the frame itself, so leave room above the budget when you set it: ```typescript Typescript/Javascript const iframe = document.querySelector('#kernel-live-view'); @@ -147,7 +147,7 @@ function arm() { iframe.src = 'about:blank'; iframe.src = src; arm(); - }, 15000); + }, 60000); } window.addEventListener('message', (event) => { @@ -161,9 +161,9 @@ window.addEventListener('message', (event) => { arm(); ``` -Do not gate on `KERNEL_CONNECTION_TIMEOUT` alone. The watchdog behind it is cleared once negotiation begins, so a connection that stalls after that point never emits it. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled. +Don't gate on `KERNEL_CONNECTION_TIMEOUT` alone. It only covers a connect that is still negotiating: the media bound clears once ICE reaches `connected` or `completed`, and a viewer whose frames stop after it connected never emits one. Log it alongside `KERNEL_PLAYING` to capture the connection state at the moment things stalled. -`KERNEL_CONNECTION_FAILED` and `KERNEL_CONNECTION_TIMEOUT` are both terminal, and a failed connect posts one of them, never both. Whichever arrives, nothing further happens until the iframe reloads. Surface a persistent message rather than remounting blindly: a `peer` or `unsupported` reason is a property of the browser environment, so a remount repeats it, while a `transport` reason is worth one retry. +`KERNEL_CONNECTION_FAILED` and `KERNEL_CONNECTION_TIMEOUT` are both terminal, and a failed connect posts one of them, never both. Whichever arrives, nothing further happens until the iframe reloads. Surface a persistent message rather than remounting blindly. `unsupported`, and a `peer` reason from peer construction or the remote offer, are properties of the browser environment, so a remount repeats them. A `transport` reason, or a `peer` reason from ICE reaching `failed` or `closed`, can come from the network path instead, so give those one retry. The client does not retry a connect itself, so whatever `reason` you get is the first failure, and whether to try again is your call.