Stop reading stdout after last sentinel appears

This commit is contained in:
Chris Wanstrath 2026-03-12 15:19:08 -07:00
parent 6138d31f58
commit 870bc8e398

View File

@ -228,13 +228,12 @@ export async function runFile(
proc.stdin.end() proc.stdin.end()
const totalTimeout = options.timeout * file.commands.length const totalTimeout = options.timeout * file.commands.length
const stdout = await readWithTimeout(proc.stdout, totalTimeout) const lastSentinelSuffix = `_${file.commands.length - 1}__`
const stdout = await readUntilSentinel(proc.stdout, sentinel, lastSentinelSuffix, totalTimeout)
if (!verbose) { if (!verbose) {
await readWithTimeout(proc.stderr, 1000).catch(() => "") await readWithTimeout(proc.stderr, 1000).catch(() => "")
} }
await proc.exited
const { outputs, exitCodes } = parseSentinelOutput( const { outputs, exitCodes } = parseSentinelOutput(
stdout, stdout,
sentinel, sentinel,
@ -262,6 +261,40 @@ export async function runFile(
} }
} }
async function readUntilSentinel(
stream: ReadableStream<Uint8Array>,
sentinelPrefix: string,
sentinelSuffix: string,
timeoutMs: number,
): Promise<string> {
const reader = stream.getReader()
const decoder = new TextDecoder()
let accumulated = ""
let timerId: ReturnType<typeof setTimeout>
const timeout = new Promise<never>((_, reject) =>
timerId = setTimeout(() => reject(new Error("Timeout reading output")), timeoutMs),
)
try {
while (true) {
const { done, value } = await Promise.race([reader.read(), timeout]) as ReadableStreamReadResult<Uint8Array>
if (done) break
if (value) {
accumulated += decoder.decode(value, { stream: true })
// Check if the last sentinel has appeared (prefix + exitcode + suffix)
const prefixIdx = accumulated.lastIndexOf(sentinelPrefix)
if (prefixIdx !== -1 && accumulated.indexOf(sentinelSuffix, prefixIdx) !== -1) break
}
}
} finally {
clearTimeout(timerId!)
reader.releaseLock()
}
return accumulated + decoder.decode()
}
async function readWithTimeout( async function readWithTimeout(
stream: ReadableStream<Uint8Array>, stream: ReadableStream<Uint8Array>,
timeoutMs: number, timeoutMs: number,