5export const k8sWaitTimeoutMs = 90 * 1000 // 90 sec 6export const imagePullTimeoutMs = 10 * 60 * 1000 // ContainerCreating (first multi-GB image pull) budget; parity with k8s progressDeadlineSeconds default (600s) 8export const throwTimedOut = (startTime: number, label: string, timeoutMs: number = k8sWaitTimeoutMs) => { 9 const elapsedMs = Date.now() - startTime 10 if (elapsedMs <= timeoutMs) return 11 const elapsedSec = Math.round(elapsedMs / 1000) 12 const msg = `TIMEOUT ${label} after ${elapsedSec}s` 18 predicate: () => Promise<unknown> // truthy = keep waiting, falsy = done 25export const pollUntil = async ({predicate, intervalMs = 3000, timeoutMs, timeoutLabel, isQuiet}: PollUntilOpts) => { 26 const startTime = Date.now() 27 const effectiveTimeoutMs = timeoutMs ?? k8sWaitTimeoutMs 28 while (await predicate()) { 29 const elapsedMs = Date.now() - startTime 30 if (elapsedMs > effectiveTimeoutMs) { 31 const elapsedSec = Math.round(elapsedMs / 1000) 32 console.error(chalkRed(`TIMEOUT ${timeoutLabel} after ${elapsedSec}s`)) 35 if (!isQuiet) process.stdout.write('.')