From dd296f703391aa67ef8cf8340e2712574b380cb1 Mon Sep 17 00:00:00 2001 From: Adam <2363879+adamdotdevin@users.noreply.github.com> Date: Thu, 12 Feb 2026 20:20:24 -0600 Subject: [PATCH] fix(app): reconnect event stream on disconnect --- packages/app/src/context/global-sdk.tsx | 87 ++++++++++++++----------- 1 file changed, 48 insertions(+), 39 deletions(-) diff --git a/packages/app/src/context/global-sdk.tsx b/packages/app/src/context/global-sdk.tsx index 346657e2f..3f93b76a7 100644 --- a/packages/app/src/context/global-sdk.tsx +++ b/packages/app/src/context/global-sdk.tsx @@ -46,6 +46,7 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo type Queued = { directory: string; payload: Event } const FLUSH_FRAME_MS = 16 const STREAM_YIELD_MS = 8 + const RECONNECT_DELAY_MS = 250 let queue: Queued[] = [] let buffer: Queued[] = [] @@ -91,50 +92,58 @@ export const { use: useGlobalSDK, provider: GlobalSDKProvider } = createSimpleCo } let streamErrorLogged = false + const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) void (async () => { - const events = await eventSdk.global.event({ - onSseError: (error) => { - if (streamErrorLogged) return - streamErrorLogged = true - console.error("[global-sdk] event stream error", { - url: server.url, - fetch: eventFetch ? "platform" : "webview", - error, + while (!abort.signal.aborted) { + try { + const events = await eventSdk.global.event({ + onSseError: (error) => { + if (streamErrorLogged) return + streamErrorLogged = true + console.error("[global-sdk] event stream error", { + url: server.url, + fetch: eventFetch ? "platform" : "webview", + error, + }) + }, }) - }, - }) - let yielded = Date.now() - for await (const event of events.stream) { - const directory = event.directory ?? "global" - const payload = event.payload - const k = key(directory, payload) - if (k) { - const i = coalesced.get(k) - if (i !== undefined) { - queue[i] = { directory, payload } - continue - } - coalesced.set(k, queue.length) - } - queue.push({ directory, payload }) - schedule() + let yielded = Date.now() + for await (const event of events.stream) { + streamErrorLogged = false + const directory = event.directory ?? "global" + const payload = event.payload + const k = key(directory, payload) + if (k) { + const i = coalesced.get(k) + if (i !== undefined) { + queue[i] = { directory, payload } + continue + } + coalesced.set(k, queue.length) + } + queue.push({ directory, payload }) + schedule() - if (Date.now() - yielded < STREAM_YIELD_MS) continue - yielded = Date.now() - await new Promise((resolve) => setTimeout(resolve, 0)) + if (Date.now() - yielded < STREAM_YIELD_MS) continue + yielded = Date.now() + await wait(0) + } + } catch (error) { + if (!streamErrorLogged) { + streamErrorLogged = true + console.error("[global-sdk] event stream failed", { + url: server.url, + fetch: eventFetch ? "platform" : "webview", + error, + }) + } + } + + if (abort.signal.aborted) return + await wait(RECONNECT_DELAY_MS) } - })() - .finally(flush) - .catch((error) => { - if (streamErrorLogged) return - streamErrorLogged = true - console.error("[global-sdk] event stream failed", { - url: server.url, - fetch: eventFetch ? "platform" : "webview", - error, - }) - }) + })().finally(flush) onCleanup(() => { abort.abort()