Flow body structure
The body is an **indent tree**: lines starting with `--` are conditions (client messages or lifecycle events); indented lines below are returns or child conditions. Line types and indentation rules are the foundation of every Flow.
| 类型 | 写法 | 说明 |
|---|---|---|
| 文件头 | # ... |
见第三节 |
| 连接推送(糖) | >> ... |
等价于 --@open 下的平级返回(见 7.4) |
| 消息条件 | --field... / --=... |
匹配 client → server 文本帧 |
| 生命周期条件 | --@... |
匹配连接/协议/定时事件(见第七节) |
| 返回 | 非 --/#/>> 的行 |
向 client 下发(server → client) |
嵌套(缩进表示父子):
- 条件的父节点:条件(消息或生命周期)或 返回
- 返回的父节点:只能是条件
- 根级:条件 或
>>;不允许根级直接写返回(无匹配上下文)
缩进:4 空格或 1 Tab,不可混用;混用 parse 报错。
同级多个 -- / --@ 条件(同一父节点、相同缩进):在 选取 entry 条件 时为 OR(§5.2、§17.3);非 entry 下平级子节点的顺序扫描规则。
同一条件下的平级多返回(顺序执行)
同一条件节点下、相同缩进的多行 返回,在 runBranch(§5.2、§17.4)扫描到该返回行时按源序发出(非并行)。 每一行是独立的一帧(或经管道后的一帧),各行可有各自的管道、+delay、!close。
延迟锚点(同一 runBranch 扫描内):
- 第一条发出的返回的 +delay:相对于「entry 条件命中时刻」(本帧 runBranch 起点)
- 后续返回的 +delay:相对于「上一条返回实际发出时刻」
- 省略 +delay 等价于 +0(紧接上一条发出后立即发)
示例:
--type=agent
{"type":"res","id":"$id","ok":true} +0ms
@fixtures/agent-event-1.json | template +300ms
@fixtures/agent-event-final.json | template +400ms
Client 发一帧 agent 请求后,Server 连发三帧:立即 ack → 300ms 后 event1 → 再 400ms 后 event2。
父条件命中后的顺序扫描(Normative)
心智模型:本质是返回;-- 条件 = 判断门,通过后发该分支下的返回。
父消息条件命中后,不对平级子节点做「只挑一个 OR 分支」;而是 按源序扫描 entry 的直接子节点:
| 直接子节点 | 本帧行为 |
|---|---|
| 返回行 | 无门控 → 发出(§5.1 delay 锚点) |
消息条件 --… |
若本帧 也匹配 → 对该子节点 递归 runBranch(scan)(§17.4;不 push 中间帧);不匹配 → 跳过 |
生命周期 --@… |
不在此扫描发返回;enter 根 runBranch 结束后按 §17.4 注册 loop 等 |
平级 返回 与平级 子条件 同一套顺序规则(不再区分「5.1 只发返回、17.3 只 execute 一条」)。
示例 A(平级返回 + 平级子条件):
--login
loginSuccess
--name=123
123
--name=234
234
Client { "login": true, "name": "123" }(同一帧)→ outbound 顺序:loginSuccess → 123(234 跳过)。
示例 B(仅平级多返回):
--login
loginSuccess
@userInfo.json
userId +2s
roomInfo
同一帧 { "login": true } → 四行返回按 §5.1 顺序连发。
示例 C(嵌套 AND,递归 runBranch):
--type=login
--password=123
--success
loginSuccess
--type=userInfo
profile
帧 { "type":"login", "password":"123", "success": true } → 扫描 --type=login 下 --password=123 匹配 → 递归 → --success 匹配 → 发出 loginSuccess(本帧 --type=userInfo 不在此次扫描路径,等下帧 scope 进入后再匹配)。
选取 entry(§17.3):每条 client 消息在匹配上下文中 仅一个 entry 条件(源序深度优先:第一条自身匹配且祖先消息条件均匹配的 -- 节点)。
同级 OR 仅作用于 多个互斥 entry(如根级 --login 与 --type=ping),不作用于 entry 内部的平级子节点扫描。
与 scope 的关系(enter 根 runBranch 结束后,见 §17.4):
- push scope 帧后,下一帧匹配上下文 = 本次 enter run 全程(含递归 scan)中 源序最后一条「已发出返回且带缩进子条件」的返回节点 之子树
- 若不存在 such 返回 → 匹配上下文 = entry 条件节点 的整棵子树
- 约定:若希望下帧只匹配某返回下分支,应将后续
--缩进在该 返回行 之下(示例 C)