From 5776b9b4e65363bbf4be18a46469c9efdb0b5eb7 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Fri, 19 Jun 2026 07:13:55 +0200 Subject: [PATCH] fix(e2e): cancel kitchen probe body reads on abort --- scripts/e2e/kitchen-sink-rpc-walk.mjs | 8 +++-- test/scripts/kitchen-sink-rpc-walk.test.ts | 34 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/scripts/e2e/kitchen-sink-rpc-walk.mjs b/scripts/e2e/kitchen-sink-rpc-walk.mjs index 311def5c8a76..9685cafaedcb 100644 --- a/scripts/e2e/kitchen-sink-rpc-walk.mjs +++ b/scripts/e2e/kitchen-sink-rpc-walk.mjs @@ -918,10 +918,12 @@ export async function fetchJson(url, options = {}) { timeoutPromise, ...(abortPromise ? [abortPromise] : []), ]); + const bodyAbortPromise = abortPromise + ? Promise.race([timeoutPromise, abortPromise]) + : timeoutPromise; const text = await Promise.race([ - readBoundedResponseText(response, maxBodyBytes, timeoutPromise), - timeoutPromise, - ...(abortPromise ? [abortPromise] : []), + readBoundedResponseText(response, maxBodyBytes, bodyAbortPromise), + bodyAbortPromise, ]); let body = null; try { diff --git a/test/scripts/kitchen-sink-rpc-walk.test.ts b/test/scripts/kitchen-sink-rpc-walk.test.ts index 3e6366dc08e7..17f9439fe1de 100644 --- a/test/scripts/kitchen-sink-rpc-walk.test.ts +++ b/test/scripts/kitchen-sink-rpc-walk.test.ts @@ -1968,6 +1968,40 @@ describe("kitchen-sink RPC process sampling", () => { expect(canceled).toBe(true); }); + it("cancels stalled HTTP probe response streams when the external signal fires", async () => { + let readStarted = false; + let canceled = false; + const controller = new AbortController(); + const fetchImpl = vi.fn().mockResolvedValue( + new Response( + new ReadableStream({ + pull() { + readStarted = true; + return new Promise(() => {}); + }, + cancel() { + canceled = true; + }, + }), + { status: 200 }, + ), + ); + + const result = fetchJson("http://127.0.0.1:19680/readyz", { + attempts: 1, + fetchImpl, + signal: controller.signal, + timeoutMs: 30_000, + }); + const rejection = expect(result).rejects.toThrow("gateway exited before ready"); + + await waitFor(() => readStarted); + controller.abort(new Error("gateway exited before ready")); + + await rejection; + await waitFor(() => canceled); + }); + it("times out stalled HTTP probe response bodies", async () => { vi.useFakeTimers(); const fetchImpl = vi.fn().mockResolvedValue({