From 1de9b67fd3273a7ca3d97867206d1c445a687249 Mon Sep 17 00:00:00 2001 From: Chris Farhood Date: Sat, 25 Apr 2026 20:37:49 +0000 Subject: [PATCH] fix: make log reconnect backoff interruptible by stop signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The exponential backoff sleep in streamPodLogs used a single setTimeout for the full delay (3s, 6s, 12s...). When logStopSignal.stopped was set mid-backoff (e.g. by external cancel), the loop body could not check the signal until the timer expired — causing the cancel test to time out when the 12s backoff overlapped with the 15s cancel window. Sleep in 200ms chunks so a stop signal can exit the backoff immediately. Fixes the pre-existing CI timeout in execute.test.ts. Co-Authored-By: Paperclip --- src/server/execute.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/server/execute.ts b/src/server/execute.ts index cbdfb41..fd9a2cf 100644 --- a/src/server/execute.ts +++ b/src/server/execute.ts @@ -287,11 +287,18 @@ async function streamPodLogs( // Exponential backoff before reconnecting: start at 3s, double each // attempt, cap at 30s. Avoids hammering the API server during prolonged // network hiccups while staying responsive for brief disconnects. + // Sleep in 200ms chunks so a stop signal can interrupt the backoff + // without waiting for the full delay to expire. const backoffMs = Math.min( LOG_STREAM_RECONNECT_MAX_DELAY_MS, LOG_STREAM_RECONNECT_DELAY_MS * 2 ** (attempt - 1), ); - await new Promise((resolve) => setTimeout(resolve, backoffMs)); + const backoffDeadline = Date.now() + backoffMs; + while (!stopSignal?.stopped) { + const remaining = backoffDeadline - Date.now(); + if (remaining <= 0) break; + await new Promise((resolve) => setTimeout(resolve, Math.min(200, remaining))); + } } // Flush any buffered partial line so the final assistant/result chunk