Bladeren bron

fix(app): reconnect event stream on disconnect

Adam 2 maanden geleden
bovenliggende
commit
dd296f7033
1 gewijzigde bestanden met toevoegingen van 46 en 37 verwijderingen
  1. 46 37
      packages/app/src/context/global-sdk.tsx

+ 46 - 37
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<void>((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
+          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 wait(0)
+          }
+        } catch (error) {
+          if (!streamErrorLogged) {
+            streamErrorLogged = true
+            console.error("[global-sdk] event stream failed", {
+              url: server.url,
+              fetch: eventFetch ? "platform" : "webview",
+              error,
+            })
           }
-          coalesced.set(k, queue.length)
         }
-        queue.push({ directory, payload })
-        schedule()
 
-        if (Date.now() - yielded < STREAM_YIELD_MS) continue
-        yielded = Date.now()
-        await new Promise<void>((resolve) => setTimeout(resolve, 0))
+        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()