From 4eb53f2b06b960982964b90d79485a12e539831c Mon Sep 17 00:00:00 2001 From: Durable Workflow Date: Thu, 22 Oct 2026 22:45:51 +0000 Subject: [PATCH] Keep the logging verifier alive while a health request is pending AbortSignal.timeout's timer is unreferenced. When a pending health request held no referenced handle, Node ended with an unsettled top-level await (exit 13) before any role was checked, as in PR #673's job 120103799105. A referenced timer always aborts the request, so the poll retries. --- scripts/ci/verify-container-logging.mjs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/ci/verify-container-logging.mjs b/scripts/ci/verify-container-logging.mjs index 4c65ba9e6..59352c02b 100644 --- a/scripts/ci/verify-container-logging.mjs +++ b/scripts/ci/verify-container-logging.mjs @@ -59,11 +59,18 @@ async function waitForApi(name) { const port = docker(['port', name, '8080/tcp']).split(':').at(-1); // Poll serially so startup cannot accumulate concurrent health requests. for (let attempt = 0; attempt < 100; attempt += 1) { + // AbortSignal.timeout's timer does not keep Node running, so a request + // left on an unreferenced keep-alive socket could end the process with an + // unsettled await (exit 13). A referenced timer always aborts it. + const controller = new AbortController(); + const timer = setTimeout(() => controller.abort(), 1000); try { - const response = await fetch(`http://127.0.0.1:${port}/api/health`, {signal: AbortSignal.timeout(1000)}); + const response = await fetch(`http://127.0.0.1:${port}/api/health`, {signal: controller.signal}); await response.text(); if (response.status === 200) return; - } catch { /* The real API may still be starting. */ } + } catch { /* The real API may still be starting. */ } finally { + clearTimeout(timer); + } await pause(100); } assert.fail('API did not become live within its original probe budget');