/** * 通用轮询工具:等到断言函数返回 truthy,或超时。 * 用于核心业务 E2E 中"提交生成 → 轮询进度"这种需要等待 LLM/TTS 的场景。 */ export interface PollOptions { /** 单次间隔 ms,默认 3000 */ intervalMs?: number; /** 总超时 ms,默认 300000 (5 分钟) * 生产环境 1000 字 LangGraph 全链路实测 3 分 48 秒,留 1 分余量。 * 之前 180s 在生产会刚好超时 48 秒导致 CORE-3 误报失败。 */ timeoutMs?: number; /** 自定义日志前缀 */ label?: string; } export async function pollUntil( fn: () => Promise, opts: PollOptions = {} ): Promise { const intervalMs = opts.intervalMs ?? 3000; const timeoutMs = opts.timeoutMs ?? 300_000; const label = opts.label ?? 'poll'; const started = Date.now(); // eslint-disable-next-line no-constant-condition while (true) { const result = await fn(); if (result) return result; if (Date.now() - started >= timeoutMs) { throw new Error( `[${label}] 轮询超时 (${Math.round(timeoutMs / 1000)}s),最后一次结果为 ${JSON.stringify(result)}` ); } await sleep(intervalMs); } } export function sleep(ms: number): Promise { return new Promise((r) => setTimeout(r, ms)); }