Flow 正文结构

正文是一棵**缩进树**:`--` 开头的是条件(匹配客户端消息或生命周期事件),其下缩进的是返回或子条件。理解行类型与缩进规则,是写对任何 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 顺序:loginSuccess123(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)