Files
qinglong/docs/adr/ADR-0112-versioned-worker-activation-transport-and-explicit-headless-lifecycle.md

7.0 KiB
Raw Permalink Blame History

ADR-0112:版本化 Worker Activation Transport 与显式 Headless Lifecycle

  • 状态:Accepted
  • 日期:2026-07-23
  • 关联 RFCQL-RFC-0001 D-05、D-06、D-85、D-108、D-109、D-110、D-111
  • 关联 ADRADR-0013、ADR-0059、ADR-0061、ADR-0109、ADR-0110、ADR-0111

背景

ADR-0111 已把 delivery inbox 原位升级为执行 authority,但 Processor 仍只依赖抽象 activation port。控制面 starting|running|start-failure 此前直接返回内部 RemoteRunActivationResult,没有版本字段、exact shape 或 response byte 上限;Worker 若各自实现 Offer 和 Activation HTTPS,会重复 Agent、证书读取、超时和错误语义。生产 组合若在 import 时启动 poll timer,又会让默认关闭失效,并让低配路由器承担不可见的 常驻资源。

决策

1. Activation response 使用版本化 exact wire contract

@qinglong/runtime-core/remote-activation-delivery 定义 qinglong/remote-run-activation@v1response 最大 16 KiB,固定为:

  • schema
  • statusapplied|already_starting|already_running|already_terminal
  • 完整 snapshotRun/Attempt identity、status、Lease version/generation、callback sequence,以及受限的时间、executor、artifact 和 error 字段。

parser 拒绝未知字段、缺失 fence、未知状态、越界整数、控制字符、错误 schema、非法 JSON 和超限字节。Cluster ingress 必须先从内部结果构造受审 response;内部 repository 返回坏 projection 时映射为 503,而不是把不可信内部数据直接发给 Worker。

Worker request 不发送 workerId/sessionId body 字段,由认证路径绑定;Processor 的 event ID 也不跨 wire,控制面 service 继续生成数据库事件 ID。lease token 是必要的短期 capability,只出现在请求,永不出现在 response、日志或 activation snapshot。

2. Offer 与 Activation 共用一个 Worker ingress HTTPS authority

WorkerIngressHttpsClientworker-runtime 同一 subpath 内的受限原语:

  • TLS 1.3、mTLS、canonical ql3w authorization
  • 默认对唯一 origin 保持单 keep-alive socketmaxSockets/maxFreeSockets=1
  • 4 KiB request、调用方给定且不超过 128 KiB 的 response 上限;
  • 只允许受审 Worker ingress path;拒绝重定向、压缩、非 JSON、非 200、错误长度和流式 越界;
  • 每次调用重新从同一 credential provider 取材,默认 Agent 使用包含 certificate、key 与 trust anchors 的 SHA-256 指纹作为不可变池键,不把随后清零的 TLS Buffer 内容作为池身份;临时 certificate/key/body 副本在结束后清零,显式 close() 释放自有 Agent。Node 会在 socket 回收时重新计算 HTTPS 池键,因此自定义受审 Agent 也必须保证池键不引用可变凭据 Buffer。

Offer transport 保留旧构造方式,同时允许注入共享 client。Activation client 只接受共享 client,不能隐式创建第二个 Agent。IP origin 不发送 SNIDNS origin 才发送 servername。 集群型 Worker 若确有连接并发需求,可显式注入受审 Agent;该 Agent 必须按 origin 与凭据 generation 隔离连接、对排队和空闲连接设界,协议与 capability authority 不随规模变化。

3. Headless lifecycle 默认关闭且不拥有 timer

WorkerRemoteExecutionHeadlessLifecycle 只组合注入的 journal、Pull coordinator、 Processor 和当前 Session provider。模块 import 与 constructor 不取得 lock、不打开 socket、 不创建 timer;只有显式 start() 才取得唯一 journal ownership。

首次启动以最多 64 条一页、默认 16 条一 tick 的 keyset 分页扫描历史 inbox。完整扫描结束 前不 Pull 新任务。可继续的 accepted|starting_acknowledged|launching|started|start_failed 交给同一 Processor;任何既有或新产生的 recovery_required 都使 lifecycle fail closed 后续 tick 不再 Pull。历史扫描完成后,每 tick 最多 Pull 一个 offer,并在同一显式调用中 交给 Processor。并发 tick 合并为一个 Promise。

stop() 先切换为 stopping、Abort 当前 Pull、等待 in-flight 工作结束,再释放 journal ownership。lifecycle 本身不设置 drain timeout;最终部署组合根使用既有全局 shutdown budget 裁决超时,避免每个小组件各建 timer。

4. Profile 与包边界不变

本决策不新增 workspace package。wire contract 位于 runtime-core subpath;共享 HTTPS、 Activation adapter 与 lifecycle 位于既有 worker-runtime remote-offer-delivery subpath。 Worker 根入口继续不导出或 eager-load 网络、journal、runtime-core 与 Executor 组合。

本 ADR 只开放可测试的生产组合 seam,不启用默认 Remote Worker 执行。Secret/Artifact/log materializer、具体 Executor、completion/lease-loss/cancellation/retry/recovery authority 未闭合 前,Profile 入口不得自动调用 start()

被否决的替代方案

  1. 直接返回内部 activation object:没有版本、exact shape 和内部坏数据隔离。
  2. Offer 与 Activation 各建 HTTPS client:重复 Agent、证书 authority 与资源预算。
  3. 把 Worker/event identity 全放 body:形成路径、认证 Principal 与 body 三份可漂移身份。
  4. lifecycle constructor 自动启动 interval:禁用后仍有 timer/lock/socket,破坏 Profile 可裁剪性。
  5. 启动扫描未完成就 Pull:可能在后页已有 ambiguous spawn 时继续接收新工作。
  6. 为 activation transport 或 lifecycle 新拆 package:没有独立部署、权限或供应链责任, 只会回退 ADR-0087/0106 的 package 收敛。

影响与剩余门禁

已完成:版本化 activation response、严格 parser、Cluster ingress 投影、共享单 Agent 的 Offer/Activation client、真实 TLS 1.3 mTLS exchange、authority mismatch/unknown field/size 负向测试,以及显式 ownership、分页 startup reconciliation、tick coalescing、Abort-before- release 与 recovery fail-closed lifecycle。

ADR-0113 已完成有界 Secret/Artifact/log materializer seam 与 log identity handoff。仍未完成: 受审的具体 Secret/Artifact provider、具体 Executor、completion transport、 heartbeat/certificate/lease renewal 组合、lease-loss 与 cancellation/retry recovery、终态 inbox retention/GC、Profile shutdown 总预算,以及 Edge/集群节点长期资源与故障注入证据。因此默认 Worker 入口仍关闭远端执行。

验收证据

  1. activation contract round-trip,并拒绝 schema drift、未知字段、空终态 snapshot 和超限响应。
  2. Offer 与三种 activation 请求观察到同一 Agentevent ID、Worker path identity 不进入 body。
  3. 真实回环 server 只接受 TLS 1.3 受信 client certificate,并观察 canonical Worker credential。
  4. lifecycle 未 start() 时零副作用;启动扫描未完成或存在 recovery 时 Pull 调用数为零。
  5. 并发 tick 合并;stop 的顺序为 Abort Pull、等待、释放 owner。
  6. workspace package 数不增加,默认 Worker root import 仍不加载 remote execution subpath。