Procházet zdrojové kódy

tui: fix event subscription cleanup in SDK context

Dax Raad před 2 měsíci
rodič
revize
50c40a8d99
1 změnil soubory, kde provedl 40 přidání a 33 odebrání
  1. 40 33
      packages/opencode/src/cli/cmd/tui/context/sdk.tsx

+ 40 - 33
packages/opencode/src/cli/cmd/tui/context/sdk.tsx

@@ -1,7 +1,8 @@
 import { createOpencodeClient, type Event } from "@opencode-ai/sdk"
 import { createSimpleContext } from "./helper"
 import { createGlobalEmitter } from "@solid-primitives/event-bus"
-import { batch, onCleanup } from "solid-js"
+import { batch, onCleanup, onMount } from "solid-js"
+import { iife } from "@/util/iife"
 
 export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
   name: "SDK",
@@ -16,43 +17,49 @@ export const { use: useSDK, provider: SDKProvider } = createSimpleContext({
       [key in Event["type"]]: Extract<Event, { type: key }>
     }>()
 
-    sdk.event.subscribe().then(async (events) => {
-      let queue: Event[] = []
-      let timer: Timer | undefined
-      let last = 0
-
-      const flush = () => {
-        if (queue.length === 0) return
-        const events = queue
-        queue = []
-        timer = undefined
-        last = Date.now()
-        // Batch all event emissions so all store updates result in a single render
-        batch(() => {
-          for (const event of events) {
-            emitter.emit(event.type, event)
-          }
+    onMount(async () => {
+      while (true) {
+        if (abort.signal.aborted) break
+        const events = await sdk.event.subscribe({
+          signal: abort.signal,
         })
-      }
+        let queue: Event[] = []
+        let timer: Timer | undefined
+        let last = 0
+
+        const flush = () => {
+          if (queue.length === 0) return
+          const events = queue
+          queue = []
+          timer = undefined
+          last = Date.now()
+          // Batch all event emissions so all store updates result in a single render
+          batch(() => {
+            for (const event of events) {
+              emitter.emit(event.type, event)
+            }
+          })
+        }
 
-      for await (const event of events.stream) {
-        queue.push(event)
-        const elapsed = Date.now() - last
+        for await (const event of events.stream) {
+          queue.push(event)
+          const elapsed = Date.now() - last
 
-        if (timer) continue
-        // If we just flushed recently (within 16ms), batch this with future events
-        // Otherwise, process immediately to avoid latency
-        if (elapsed < 16) {
-          timer = setTimeout(flush, 16)
-          continue
+          if (timer) continue
+          // If we just flushed recently (within 16ms), batch this with future events
+          // Otherwise, process immediately to avoid latency
+          if (elapsed < 16) {
+            timer = setTimeout(flush, 16)
+            continue
+          }
+          flush()
         }
-        flush()
-      }
 
-      // Flush any remaining events
-      if (timer) clearTimeout(timer)
-      if (queue.length > 0) {
-        flush()
+        // Flush any remaining events
+        if (timer) clearTimeout(timer)
+        if (queue.length > 0) {
+          flush()
+        }
       }
     })