运行并行 Branch 与安全 Race
预留共享预算、持久化 Branch 进度、确定性 Join、快速失败,并且只对副作用安全工作执行 Race。
并行契约
并行 Workflow 是受治理的 Fan-out/Fan-in Node,而不是一组 Detached Future。每个唯一命名
ParallelBranch 接收同一个 Canonical Input、衰减后的 Capability Set、预留预算份额与
子 Run。
所有 Branch 必须全部 Admission 后才开始。Join Output 按稳定 Step Identity 组织,因此 完成时序不会改变输出顺序。
预算预留
只有原子 Counter 时,最快 Branch 可以消耗全部剩余预算。Batch Reservation 为每个 Sibling 分配确定性最大所有权。Batch 要么全部成功,要么不改变任何状态;Scoped Tracker 无法消费 其他 Branch 的份额。
消费转成已提交 Run Usage。最后一个 Scoped Reservation 释放时,未用容量归还。Reservation 应表达可接受最大值,而不是乐观平均值。
持久 Branch 状态
Checkpoint 把每个 Branch 记录为 In-flight、带 Output 的 Completed 或 Failed。成功 Output 独立持久化。恢复不会重跑 Completed Branch;Incomplete Work 需要显式 Retry Authority。
Fail-fast Parallel 会记录失败 Branch 并取消未完成 Sibling。取消是协作式的,不能证明远程 调用停止,也不会撤销 Effect。
First-success Race
Race 返回第一个成功 Canonical Output,但只接受 Pure 与 ReadOnly Capability。Idempotent Write 仍被拒绝:幂等避免重复写,不会让 Losing Branch 的非预期写变得合理。
Winner 产生前,每个 Branch 都至少 Poll 一次。Loser 被取消,并保守 Forfeit 未用 Reservation, 因为远端 Usage 可能继续但不再返回终止事件。
选择策略
需要所有结果时使用 Parallel Fan-out;延迟重要、Route 只读且能接受最坏 Losing Cost 时使用 Race;第一 Route 可以在第二 Route 开始前安全失败时使用顺序 Fallback;外部写需要确定顺序时 避免并发。
生产前记录 Branch Authority、Reservation、Failure Policy、Checkpoint 行为与协调方式。
构建有界 Parallel Node
let per_branch = Usage { turns: 1, ..Usage::default() };
let workflow = Workflow::builder("parallel-analysis")
.parallel("analyze", [
ParallelBranch::step(
"risk", RiskStep, CapabilitySet::new(), per_branch,
),
ParallelBranch::step(
"value", ValueStep, CapabilitySet::new(), per_branch,
),
])
.build()?;
let run = RunContext::root(
BudgetTracker::new(Budget { turns: Some(2), ..Budget::default() }),
CapabilitySet::new(),
);
let outcome = workflow.run("proposal", &run).await?;Join 后的 JSON Object 按稳定 Branch ID 排列,与实际完成顺序无关。任何 Branch 开始前,
Parent Budget 必须能够一次性接纳全部 Reservation。race(...) 使用同样结构,但只能
授予 Pure 或 ReadOnly Capability;Builder 会拒绝有写权限的 Branch。