BLOGE
0.9.9-RC1在线版 · 编制 2026-11-02 · English
第 11 章 —— 批处理与迭代
承诺: 读完本章后,你将知道如何使用
foreach处理集合中的每一项,使用loop重复工作直到条件满足,并在单个 graph 中组合这两种构造——所有这些都无需在 operator 代码中编写任何for/while循环。
学习目标
- 编写一个
foreach块,对集合进行扇出——默认并行或顺序执行——并在主体中引用当前项和索引。 - 编写一个包含
until、max_iterations、delay和carry的loop块,表达有界迭代并在轮次之间转发状态。 - 使用三个 loop 特有的隐式变量 ——
carry.<path>、prev.<nodeId>.<path>和loopIteration—— 并解释每个变量在运行时如何解析。 - 在下游节点中使用
depends_on消费foreach或loop的聚合输出。 - 识别
foreach和loop何时可以在同一个 graph 中组合——以及何时stream foreach/stream loop是更好的选择。
前置条件
- 第 10 章 —— 用子图复用 —— 你需要理解
foreach和loop的主体会被编译为嵌套子图。
源示例
| 文件 | 展示内容 |
|---|---|
batch-order-processing.bloge | 最简单的并行 foreach —— 获取订单、验证、处理 |
batch-order-parallel.bloge | 并行 foreach,带有下游 summarize 节点消费聚合输出 |
sequential-transfer.bloge | foreach … sequential —— 逐一执行的银行转账 |
status-polling.bloge | 基本的 loop,带 until 和 loopIteration —— 轮询直到 READY |
cursor-pagination.bloge | 带多字段 carry 的 loop —— API 游标分页 |
retry-with-backoff.bloge | 基于 loop 的自定义重试,带 carry 和 loopIteration |
logistics-batch-dispatch.bloge | 同一个 graph 中的 foreach + loop —— 调度包裹,然后轮询状态 |
basic.bloge (foreach) | 一致性测试 fixture:最小的 foreach |
sequential-index.bloge | 一致性测试 fixture:带索引绑定的 foreach … sequential |
with-carry.bloge | 一致性测试 fixture:带 carry、prev 和 loopIteration 的 loop |
为什么这很重要
到目前为止,你的 graph 中每个节点最多运行一次。真实系统很少这么简单:
- 一个电商结账流程必须验证每一条订单行——而不是只验证一条。
- 一个数据同步任务必须翻页遍历 API 的所有页面,并向前传递游标。
- 一个部署流水线必须轮询外部系统,直到状态变为 READY。
在过程式代码中,你会使用 for 或 while。在 BLOGE 中,等价的构造是 foreach(处理集合中的每一项)和 loop(重复直到条件成立)。两者都是超级节点(hyper-node):它们在外层 graph 中表现为单个节点,但内部会编译为一个嵌套子图,引擎会像对待其他 graph 一样对其进行调度、重试和观测。
核心好处是:迭代语义——并行度、顺序、有界重试、carry 状态——都声明在 DSL 中,而不是埋在 operator 代码里。引擎拥有循环;你的 operator 只需处理单个项或单次迭代。