Lifecycle (--@)

Lifecycle conditions are connection events, not app messages: `--@open`, `--@loop`, `--@ping`, `--@close`. Use them for welcome frames, heartbeats, and protocol Pong.

生命周期条件匹配 非 client JSON 业务帧,而是连接/协议/定时事件。 语法:行首 --@ + 事件名(+ 可选参数)。@ 为保留字,业务 JSON 字段勿与 --@ 混淆。

事件一览

条件 触发时机 次数 典型用途
--@open Mock 接管连接,WS 握手完成 每连接 1 次 welcome、challenge、初始推送
--@ping 收到 client 协议级 Ping 帧 每次 ping 自定义 pong(否则 # ping auto)
--@pong 收到 client 协议级 Pong 帧 每次 pong 少见;可忽略或日志
--@close 收到 Close 帧或连接即将结束 每连接至多 1 次 最后一帧通知、清理
--@loop <dur> 连接存活期间定时 周期性 tick、heartbeat、行情推送

<dur> 格式:500ms、2s、1m、5s;纯数字无单位视为毫秒(如 5000 = 5000ms)。

解析优先级(条件行统一入口)

  1. 行首 --@ → 生命周期条件(本节)
  2. 否则 → 第六节消息条件

各事件语义

--@open

  • Flow match 命中且连接建立后触发一次
  • 其下平级返回按 5.1 顺序发出(server 主动推送,无需 client 先发消息)
  • 可挂子条件(消息或生命周期),发完 open 返回后按 scope 规则进入子树
  • 可选 capture(实现):$connectionId、$subprotocol 写入连接上下文
  • 典型:连上发 challenge → 等 client auth → 再开 tick
  --@open
      {"type":"challenge","nonce":"mock-nonce"} +0ms
      --type=connect
          {"type":"connected","ok":true} +0ms
              --@loop 10s
                  {"type":"tick"} +0ms

--@ping / # ping auto

  • 协议级 Ping(WebSocket opcode ping),payload 可为空
  • # ping auto on:未命中 --@ping 时,runtime 自动回 protocol Pong(空 payload)
  • --@ping 下返回:按返回行发出 text 帧(若写 "pong");不自动混用 protocol pong
  • Mock 且 # upstream off 时:validate 要求 # ping auto on 或存在 --@ping(否则 E008)
  • 与应用层 --type=ping 无关

--@pong

  • 协议级 Pong;多数场景无需分支,预留供测试/日志。

--@close

  • client 发 Close 或连接 teardown 时触发
  • 其下返回:断线前最后一帧(若来得及发出)
  • 触发后取消该连接所有 --@loop 定时器
  • 不替代 server 主动关连接;主动关见 8.3 !close

--@loop <dur>

  • 连接存活期间,每隔 dur 触发一次(server 主动推送)
  • 其下返回:每次 tick 执行(支持管道、$、+delay;+delay 相对 tick 触发时刻)
  • 绑定 scope 栈帧:仅在其 所属 scope 帧 active 期间运行(见第十七节)
  • 进入 scope 且到达 loop 节点 → register timer;离开 scope 帧(pop)→ cancel
  • 连接关闭或 --@close → cancel 该连接全部 timer
  • 首 tick:# loop immediate off 时首个 tick 在 dur 之后;on 时注册后立即 tick

--@loop 注册时机表(Normative)

位置 start stop
根级(与 --@open 同级) WS 建立且 Flow 命中后,root 帧 active 连接关闭 / !close / --@close
--@open 的直接子节点 --@open 触发且 open 下 同级返回发完 离开 --@open 子树 scope / !~session 等 pop
挂在返回子树深处 scope 激活且 遍历到达 loop 节点 pop 该 loop 所在帧或任意祖先帧
--login ~auth 等命名 scope 内 进入 ~auth 帧 active 后 !~auth 或 pop auth 及其祖先

同一 scope 帧上多个 --@loop 兄弟:各自独立 timer。

>>--@open 的关系

根级 >> 是语法糖,编译为:

  --@open
      <原 >> 行内容>

多条根级 >> 合并为同一 --@open 下的平级多返回(5.1 顺序执行)。

需要「连上推送 + 后续 scope」时,请写完整 --@open 树,不要仅用散装 >>

生命周期条件与 capture

# capture 默认只对 消息条件 匹配成功的 JSON 帧生效。 --@open 等生命周期事件不 capture client JSON(无帧或无可 parse JSON)。 实现可选:--@open 时 capture 连接元数据到 $connectionId 等。

生命周期 + scope

与消息条件相同:--@open 等触发 enter 根 runBranch(§17.4)— 顺序扫描平级子节点;enter 结束后 push 帧并移入匹配上下文(§5.2、§17.4)。 缩进在 返回行 下的子条件:下帧在 scope 移入后匹配;与 entry 平级 的子 -- 可在 同帧 scan 中匹配(§5.2)。 --@loop 作为子条件时,在 enter 结束且 scope 帧激活 后 register(步骤 5);该帧 pop 时 cancel。 命名 scope 规则见 6.9 与第十一节。