7.0 KiB
ADR-0112:版本化 Worker Activation Transport 与显式 Headless Lifecycle
- 状态:Accepted
- 日期:2026-07-23
- 关联 RFC:QL-RFC-0001 D-05、D-06、D-85、D-108、D-109、D-110、D-111
- 关联 ADR:ADR-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@v1,response 最大 16 KiB,固定为:
schema;status:applied|already_starting|already_running|already_terminal;- 完整
snapshot:Run/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
WorkerIngressHttpsClient 是 worker-runtime 同一 subpath 内的受限原语:
- TLS 1.3、mTLS、canonical
ql3wauthorization; - 默认对唯一 origin 保持单 keep-alive socket,
maxSockets/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 不发送 SNI,DNS 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()。
被否决的替代方案
- 直接返回内部 activation object:没有版本、exact shape 和内部坏数据隔离。
- Offer 与 Activation 各建 HTTPS client:重复 Agent、证书 authority 与资源预算。
- 把 Worker/event identity 全放 body:形成路径、认证 Principal 与 body 三份可漂移身份。
- lifecycle constructor 自动启动 interval:禁用后仍有 timer/lock/socket,破坏 Profile 可裁剪性。
- 启动扫描未完成就 Pull:可能在后页已有 ambiguous spawn 时继续接收新工作。
- 为 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 入口仍关闭远端执行。
验收证据
- activation contract round-trip,并拒绝 schema drift、未知字段、空终态 snapshot 和超限响应。
- Offer 与三种 activation 请求观察到同一 Agent;event ID、Worker path identity 不进入 body。
- 真实回环 server 只接受 TLS 1.3 受信 client certificate,并观察 canonical Worker credential。
- lifecycle 未
start()时零副作用;启动扫描未完成或存在 recovery 时 Pull 调用数为零。 - 并发 tick 合并;stop 的顺序为 Abort Pull、等待、释放 owner。
- workspace package 数不增加,默认 Worker root import 仍不加载 remote execution subpath。