/** * 关键差异确认:误 resume(迟到的/重复的任务回调)会不会把整条 run 打死? * - 顶层 step 打错 → ? * - 嵌套 step(nested workflow 里的 step)打错 → ? * 路线 A 里所有节点都在嵌套的循环体里,所以这条差异对选型很关键。 * * 运行:SPIKE_NO_AUTORUN=1 tsx src/probe-05-misresume-blast-radius.ts */ import { DecisionScript, Ledger, banner } from './ledger.js'; import { mastraB, _internals as bInternals } from './route-b-external.js'; import { mastraA, _internals as aInternals } from './route-a-dowhile.js'; import { resetTrace } from './trace.js'; aInternals.setLedger(new Ledger()); aInternals.setScript(new DecisionScript([])); bInternals.setLedger(new Ledger()); bInternals.setScript(new DecisionScript([])); resetTrace(); const wfB = mastraB.getWorkflow('routeB'); const wfA = mastraA.getWorkflow('routeA'); banner('B-1:顶层 step 打错(A4 挂起时去 resume A5)'); { const run = await wfB.createRun({ runId: 'blast-top' }); await run.start({ inputData: { quoteId: 'QB', instanceSeq: 1, reopenedBy: null, prevRunId: null } }); try { const r = await run.resume({ step: ['A5'], resumeData: { verdict: 'pass' } }); console.log('返回 status =', r.status, 'error =', JSON.stringify((r as any).error ?? null)); } catch (e) { console.log('抛异常 =', (e as Error).message); } console.log('run 之后的 status =', (await wfB.getWorkflowRunById('blast-top'))?.status); const ok = await run.resume({ step: ['A4'], resumeData: { price: 1 } }); console.log('再补正确的 resume A4 → status =', ok.status, ' ← run 没被打坏,还能继续'); } banner('B-2:嵌套 step 打错(A4 挂起时去 resume A6-sub.A6)'); { const run = await wfB.createRun({ runId: 'blast-nested' }); await run.start({ inputData: { quoteId: 'QB2', instanceSeq: 1, reopenedBy: null, prevRunId: null } }); try { const r = await run.resume({ step: ['A6-sub', 'A6'], resumeData: { outcome: 'won' } }); console.log('返回 status =', r.status, 'error =', JSON.stringify((r as any).error ?? null)); } catch (e) { console.log('抛异常 =', (e as Error).message); } const st = await wfB.getWorkflowRunById('blast-nested'); console.log('run 之后的 status =', st?.status); try { const ok = await run.resume({ step: ['A4'], resumeData: { price: 1 } }); console.log('再补正确的 resume A4 → status =', ok.status); } catch (e) { console.log('再补正确的 resume A4 抛异常 =', (e as Error).message, ' ← 这一单救不回来了'); } } banner('A-1:路线 A 里所有节点都在嵌套循环体里,打错一次会怎样'); { const run = await wfA.createRun({ runId: 'blast-loop' }); await run.start({ inputData: { quoteId: 'QA' } }); try { const r = await run.resume({ step: ['round-body', 'A5'], resumeData: { verdict: 'pass' } }); console.log('返回 status =', r.status, 'error =', JSON.stringify((r as any).error ?? null)); } catch (e) { console.log('抛异常 =', (e as Error).message); } console.log('run 之后的 status =', (await wfA.getWorkflowRunById('blast-loop'))?.status); try { const ok = await run.resume({ step: ['round-body', 'A4'], resumeData: { price: 1 } }); console.log('再补正确的 resume A4 → status =', ok.status); } catch (e) { console.log('再补正确的 resume A4 抛异常 =', (e as Error).message, ' ← 这一单救不回来了'); } }