Explorar o código

core: prevent TimeoutOverflowWarning by capping setTimeout delay to max 32-bit signed integer

Aiden Cline hai 1 mes
pai
achega
9a1dc1ffe4

+ 2 - 1
packages/opencode/src/session/retry.ts

@@ -5,10 +5,11 @@ export namespace SessionRetry {
   export const RETRY_INITIAL_DELAY = 2000
   export const RETRY_BACKOFF_FACTOR = 2
   export const RETRY_MAX_DELAY_NO_HEADERS = 30_000 // 30 seconds
+  export const RETRY_MAX_DELAY = 2_147_483_647 // max 32-bit signed integer for setTimeout
 
   export async function sleep(ms: number, signal: AbortSignal): Promise<void> {
     return new Promise((resolve, reject) => {
-      const timeout = setTimeout(resolve, ms)
+      const timeout = setTimeout(resolve, Math.min(ms, RETRY_MAX_DELAY))
       signal.addEventListener(
         "abort",
         () => {

+ 20 - 0
packages/opencode/test/session/retry.test.ts

@@ -58,6 +58,26 @@ describe("session.retry.delay", () => {
     const longError = apiError({ "retry-after-ms": "700000" })
     expect(SessionRetry.delay(1, longError)).toBe(700000)
   })
+
+  test("sleep caps delay to max 32-bit signed integer to avoid TimeoutOverflowWarning", async () => {
+    const controller = new AbortController()
+
+    const warnings: string[] = []
+    const originalWarn = process.emitWarning
+    process.emitWarning = (warning: string | Error) => {
+      warnings.push(typeof warning === "string" ? warning : warning.message)
+    }
+
+    const promise = SessionRetry.sleep(2_560_914_000, controller.signal)
+    controller.abort()
+
+    try {
+      await promise
+    } catch {}
+
+    process.emitWarning = originalWarn
+    expect(warnings.some((w) => w.includes("TimeoutOverflowWarning"))).toBe(false)
+  })
 })
 
 describe("session.message-v2.fromError", () => {