diff --git a/src/server/execute.ts b/src/server/execute.ts index 2006624..403d9de 100644 --- a/src/server/execute.ts +++ b/src/server/execute.ts @@ -470,12 +470,14 @@ async function streamAndAwaitJob( // Run the file tail and the job-completion poll in parallel so that the // tail loop has a way to stop: when waitForJobCompletion resolves it sets // stopSignal.stopped, which lets tailPodLogFile drain and return. + // No completionWithGrace wrapper here — wrapping a long-running job poll + // in a 30s grace turns the grace into a hard ceiling and kills runs + // prematurely with "Timed out after 0s" when timeoutSec is 0 (no timeout). const completionPromise = waitForJobCompletion(namespace, jobName, completionTimeoutMs, kubeconfigPath) .then((r) => { stopSignal.stopped = true; return r; }); - const completionGraced = completionWithGrace(completionPromise, LOG_EXIT_COMPLETION_GRACE_MS); const [tailSettled, completionSettled] = await Promise.allSettled([ tailPodLogFile(podLogPath, { onLog: wrappedOnLog, stopSignal }), - completionGraced, + completionPromise, ]); stdout = tailSettled.status === "fulfilled" ? tailSettled.value : ""; if (completionSettled.status === "rejected") {