Add fetch timeouts to Stop hook and health checks

Replace bare fetch() calls with fetchWithTimeout() using Promise.race
instead of AbortSignal.timeout() which causes libuv assertion crashes
in Bun on Windows.

Applies the already-defined HEALTH_CHECK_TIMEOUT_MS (30s/45s) to
isWorkerHealthy() and getWorkerVersion(), and HOOK_TIMEOUTS.DEFAULT
to the summarize POST. Previously these fetches had no timeout at all,
causing the Stop hook to hang for the full hook timeout (120s) when
the worker was unreachable.

Fixes #963
This commit is contained in:
Rod Boev
2026-02-05 10:05:44 -05:00
committed by Alex Newman
parent be01694383
commit 1dd456a6ca
2 changed files with 37 additions and 15 deletions
+16 -11
View File
@@ -7,10 +7,12 @@
*/
import type { EventHandler, NormalizedHookInput, HookResult } from '../types.js';
import { ensureWorkerRunning, getWorkerPort } from '../../shared/worker-utils.js';
import { ensureWorkerRunning, getWorkerPort, fetchWithTimeout } from '../../shared/worker-utils.js';
import { logger } from '../../utils/logger.js';
import { extractLastMessage } from '../../shared/transcript-parser.js';
import { HOOK_EXIT_CODES } from '../../shared/hook-constants.js';
import { HOOK_EXIT_CODES, HOOK_TIMEOUTS, getTimeout } from '../../shared/hook-constants.js';
const SUMMARIZE_TIMEOUT_MS = getTimeout(HOOK_TIMEOUTS.DEFAULT);
export const summarizeHandler: EventHandler = {
async execute(input: NormalizedHookInput): Promise<HookResult> {
@@ -41,15 +43,18 @@ export const summarizeHandler: EventHandler = {
});
// Send to worker - worker handles privacy check and database operations
const response = await fetch(`http://127.0.0.1:${port}/api/sessions/summarize`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contentSessionId: sessionId,
last_assistant_message: lastAssistantMessage
})
// Note: Removed signal to avoid Windows Bun cleanup issue (libuv assertion)
});
const response = await fetchWithTimeout(
`http://127.0.0.1:${port}/api/sessions/summarize`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contentSessionId: sessionId,
last_assistant_message: lastAssistantMessage
}),
},
SUMMARIZE_TIMEOUT_MS
);
if (!response.ok) {
// Return standard response even on failure (matches original behavior)