mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
feat(ql3): operationalize cancellation rearm
This commit is contained in:
@@ -11,6 +11,20 @@
|
||||
|
||||
最新增量证据(2026-08-19):
|
||||
|
||||
- D-365/ADR-0458(已接受;聚合指标与产品 UI 待完成):在既有隔离 `cluster-admin` Run management plane 上增加
|
||||
`run.cancellation.inspect` 与 `run.cancellation.rearm`,不新建 package、服务、端口、timer、连接池或 Kubernetes 对象。inspect 要求强认证 User
|
||||
与 `run.read`,viewer 可读取 Run/dispatch 的固定低敏投影,但永不返回 lease owner、raw token 或 token digest;rearm 要求 `run.stop`,只接受
|
||||
`blocked + expected dispatch version + expected blocking result` 的精确 CAS,retry delay 固定为 1 秒至 24 小时并由 PostgreSQL
|
||||
`transaction_timestamp()` 计算绝对到期时间。成功事务同时推进 Run version/event sequence、保留 blocking result 作为历史、追加
|
||||
`run.cancel_dispatch_rearmed` 与 allowed audit;mutation replay 返回同一不可变 receipt,stale result/version、终态 Run、非活跃 Attempt 或 authorization
|
||||
drift 均失败关闭。`pg-0067-cancellation-dispatch-management` 把 capability 提升至 v66,只给 `ql3_run_manager` 增加 dispatch SELECT 与
|
||||
`status/version/next_attempt_at_ms/updated_at_ms` 四列 UPDATE。真实 HA 首跑发现 `FOR KEY SHARE` 会隐含要求 Attempt UPDATE 权限,最终以既有
|
||||
SERIALIZABLE 事务、Run 行锁和普通 Attempt 读取修复,没有扩权。完整 backend `1,487 pass / 0 fail / 2 conditional skip`,18-package clean
|
||||
build/test、四项架构审计与 `14/14` Local artifact audit 通过;workspace 仍为 18 包,`cluster-postgres` 为 172 个 source(171 nested),基础
|
||||
Edge/Standalone 仍为 `2,589,998 / 2,590,076` bytes,Application+AI 为 `4,493,151 / 4,493,283` bytes。PostgreSQL 18.6 arm64 HA
|
||||
`144/144` 真实执行 blocked→低敏 inspect→CAS rearm→not-due→生产交付→WAL→promotion;timeline `1→2`,报告 SHA-256 为
|
||||
`58f43327f426c286aaa1764aa6dd9f5963a462304716e09b933f326991442b8a`。
|
||||
|
||||
- D-364/ADR-0457(已接受;运维可见性与实机容量门待完成):把 PostgreSQL CancellationDispatch 接入既有 caller-driven Remote Worker
|
||||
lease-control 生产路径,没有新建扫描 timer 或第二调度 authority。只有已有 Session/RunDispatchLease/Attempt fence 产生 `stop_requested` 后才 claim;
|
||||
`claimed` 必须先以 `termination_requested` 原子结算 dispatch 与 `run.cancel_dispatched`,验证 durable 结果后才向 Worker 释放停止响应;`dispatched`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# ADR-0005:Durable Cancellation Dispatch、Lease 与 Fencing
|
||||
|
||||
- 状态:Accepted(Local 与 PostgreSQL Repository 已实现;Cluster 生产启动拓扑待接入)
|
||||
- 状态:Accepted(Local、PostgreSQL Repository、Cluster 生产交付与人工处置入口已实现)
|
||||
- 日期:2026-07-18
|
||||
- 决策范围:跨进程取消派发、崩溃恢复、并发 Worker、退避和审计事件
|
||||
- 关联:QL-RFC-0001、ADR-0001、ADR-0003、ADR-0004
|
||||
@@ -151,13 +151,13 @@ PID 可复用,可能终止无关进程,禁止。
|
||||
|
||||
## 5. 当前孵化边界
|
||||
|
||||
`next` 已实现 profile-neutral canonical contract、`0005-run-cancellation-dispatch`、legacy Sequelize/SQLite adapter、PostgreSQL `pg-0066-cancellation-dispatch`/capability v65 adapter、lease expiry 接管、fencing、退避、结果事件、Dispatcher、有界 Supervisor 和默认惰性的 lifecycle runner。PostgreSQL 结果事务按 Run→Attempt→dispatch 锁序完成 dispatch 更新、Run version CAS 与 RunEvent 追加;runtime 角色只取得新表的 SELECT/INSERT/UPDATE。Cluster 生产交付已由 ADR-0457 接入既有 caller-driven Worker lease-control:Run-level stop 必须先结算 durable dispatch 再返回,Workflow Task timeout 则保持 `untracked`,不伪造父 Run 取消。
|
||||
`next` 已实现 profile-neutral canonical contract、`0005-run-cancellation-dispatch`、legacy Sequelize/SQLite adapter、PostgreSQL `pg-0066-cancellation-dispatch`/capability v65 adapter、lease expiry 接管、fencing、退避、结果事件、Dispatcher、有界 Supervisor 和默认惰性的 lifecycle runner。PostgreSQL 结果事务按 Run→Attempt→dispatch 锁序完成 dispatch 更新、Run version CAS 与 RunEvent 追加;runtime 角色只取得新表的 SELECT/INSERT/UPDATE。Cluster 生产交付已由 ADR-0457 接入既有 caller-driven Worker lease-control:Run-level stop 必须先结算 durable dispatch 再返回,Workflow Task timeout 则保持 `untracked`,不伪造父 Run 取消。ADR-0458 又在既有隔离 Run management plane 上增加低敏 inspect 与 exact-CAS rearm:viewer 只有 `run.read` 诊断权,rearm 继续要求 `run.stop`;任何接口都不暴露 lease owner、raw token 或 token digest。
|
||||
|
||||
HTTP worker 已通过默认关闭的 manual-only manifest bootstrap 接入 Local Supervisor:只有 accepted 且全部 gate 通过时才启动,失败或 shutdown 时有界停止。以下工作仍未完成,因此它仍只允许显式 canary,不得扩大到默认生产流量:
|
||||
|
||||
- 用户可见的运行指标、blocked 诊断和处置入口。
|
||||
- 用户可见的聚合运行指标、告警与产品 UI;私有 operator 诊断和处置协议已经实现。
|
||||
- 固定 edge 设备的数据库写放大、RSS、时延和磁盘基准。
|
||||
- cluster-control 对 PostgreSQL CancellationDispatch 的用户可见 availability/blocked 指标、诊断与人工处置入口。
|
||||
- cluster-control 对 PostgreSQL CancellationDispatch 的聚合 availability/blocked 指标与告警出口。
|
||||
- 首次真实目标实例完整激活/回滚仪式与共享 config 多写者 authority。
|
||||
|
||||
## 6. 验证门禁
|
||||
@@ -175,3 +175,5 @@ HTTP worker 已通过默认关闭的 manual-only manifest bootstrap 接入 Local
|
||||
11. PostgreSQL 双连接只能产生一个 claim winner,raw token 不落库,数据库时间决定 lease/retry 到期。
|
||||
12. v65 事实经 WAL 到达 standby,提升为新 Primary 后仍可读取;旧 owner/token/version 继续被 fencing。
|
||||
13. Cluster Worker lease-control 只在 durable dispatch 已结算或已重放时释放 Run-level stop;Workflow Task timeout 不写父 Run 取消事实。
|
||||
14. 强认证 viewer 只能读取无 lease capability 的低敏诊断;只有 `run.stop` authority 可按 blocked/version/result 精确 rearm。
|
||||
15. rearm、RunEvent 与 allowed audit 原子提交,数据库时间决定 retry due;stale fence、授权漂移与 mutation drift 均失败关闭。
|
||||
|
||||
@@ -61,4 +61,4 @@ QingLong 3.0 还必须同时服务低配路由和集群节点。公共协议需
|
||||
|
||||
## 后续
|
||||
|
||||
ADR-0457 已把 PostgreSQL CancellationDispatch Repository 接入既有 caller-driven Worker lease-control 生产 composition:它刻意不新增扫描 cadence,并复用 ingress drain 与数据库 shutdown 顺序。尚需用户可见的 availability/blocked 指标、诊断和人工处置面,以及 CloudNativePG live failover、多副本压力、固定 x64/arm64 资源门。Local 侧如需消除 legacy raw-token 存量,另开兼容迁移 ADR,不与 Cluster rollout 混合。
|
||||
ADR-0457 已把 PostgreSQL CancellationDispatch Repository 接入既有 caller-driven Worker lease-control 生产 composition:它刻意不新增扫描 cadence,并复用 ingress drain 与数据库 shutdown 顺序。ADR-0458 又通过 v66 migration 和既有 Run management plane 实现无 lease capability 的诊断与 exact-CAS rearm;没有新增连接、进程或部署对象。尚需用户可见的聚合 availability/blocked 指标、告警 UI,以及 CloudNativePG live failover、多副本压力、固定 x64/arm64 资源门。Local 侧如需消除 legacy raw-token 存量,另开兼容迁移 ADR,不与 Cluster rollout 混合。
|
||||
|
||||
@@ -59,4 +59,4 @@ Run 取消与 Workflow Task timeout 还存在语义差异:前者具有 `Run.ca
|
||||
|
||||
## 后续
|
||||
|
||||
仍需用户可见的 blocked/availability 指标、诊断与人工处置入口,以及 CloudNativePG live failover、多副本容量压力、固定 Linux x64/arm64 与物理 Edge 资源门。Local legacy raw-token 存量迁移继续保持独立议题。
|
||||
ADR-0458 已在既有 Run management plane 实现低敏 blocked 诊断与人工 rearm,不新增第二个 cancellation worker。仍需用户可见的聚合 blocked/availability 指标、告警与产品 UI,以及 CloudNativePG live failover、多副本容量压力、固定 Linux x64/arm64 与物理 Edge 资源门。Local legacy raw-token 存量迁移继续保持独立议题。
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
# ADR-0458:最小权限 CancellationDispatch 诊断与人工 Rearm
|
||||
|
||||
- 状态:Accepted
|
||||
- 日期:2026-08-19
|
||||
- 关联 RFC:QL-RFC-0001 D-365、PR-5、PR-7
|
||||
- 关联 ADR:ADR-0005、ADR-0383、ADR-0456、ADR-0457
|
||||
- Amends:ADR-0005 的 blocked 人工处置边界、ADR-0456 的 PostgreSQL Run manager authority
|
||||
|
||||
## 上下文
|
||||
|
||||
ADR-0456/0457 已让 Cluster Run cancellation 具备数据库计时、跨副本 fencing 和真实 Worker 交付,但 `identity_mismatch`、`pid_mismatch`、`unsupported`、`invalid` 会有意进入 `blocked`,禁止自动重试。没有受权诊断与人工 rearm 时,operator 只能直接查询或修改数据库;这既容易泄露 lease capability,也绕过 Project Policy、强认证、RunEvent 和安全审计。
|
||||
|
||||
QingLong 同时面向低配路由器与集群。该能力只属于 Cluster operator plane,不能扩大 Local Profile 闭包,也不应为了两个 operation 新建微包、HTTP 服务、扫描 timer 或数据库连接池。
|
||||
|
||||
## 决策
|
||||
|
||||
1. 复用既有隔离 `cluster-admin` Run management HTTPS/mTLS process、固定 `/api/v3/runs/management` 路径、OIDC assertion、速率限制、连接池和 shutdown lifecycle。新增 operation 为 `run.cancellation.inspect` 与 `run.cancellation.rearm`,不新增服务或部署对象。
|
||||
2. inspect 只接受强认证 User,授权使用既有 `run.read`。因此 viewer 可诊断,agent、弱认证、过期认证和 authorization fence drift 均失败关闭。
|
||||
3. diagnostic 只投影 Project/Run 状态、取消意图、Attempt ID、dispatch status/version/count、受限时间戳、固定 last result 与 `none|wait|rearm` 建议。lease owner、raw token、token digest、PID、handle、命令、环境、Secret 和错误原文永不进入 SQL projection、transport schema 或客户端结果。
|
||||
4. rearm 继续使用 `run.stop`,不新建更宽 permission。请求必须精确匹配 `blocked`、expected dispatch version 和 expected blocking result,并提供 1 秒至 24 小时的 retry delay;服务端生成 RunEvent ID,调用方不能塑造 event identity。
|
||||
5. Repository 使用 SERIALIZABLE 短事务和 PostgreSQL `transaction_timestamp()`。它重新锁定 Project Policy fence 与 Run,验证非终态 Run、既有 cancellation、同 Run active Attempt 和精确 dispatch CAS;绝对 `next_attempt_at_ms` 只能由数据库计算。
|
||||
6. 成功 rearm 在同一事务中推进 Run version/event sequence,把 dispatch 切换为 `retry_wait` 并递增 version,追加 `run.cancel_dispatch_rearmed` 和 allowed security audit。事件 payload 只包含 mutation、前后 version、固定 blocking result、delay、due time 与 Run version。
|
||||
7. mutation replay 先读取 immutable RunEvent,只有 actor、mutation、version、result、delay 和 receipt 全部相同时返回原 receipt;任何漂移返回 conflict,不重复更新 dispatch。
|
||||
8. rearm 保留原 blocking `last_result` 作为历史,因此 canonical/SQL 状态约束允许 `leased|retry_wait` 携带 blocking 或 retryable history;新 claim/result 仍按当前 status 与精确 fence 决定,不把历史结果当作新的 controller verdict。
|
||||
9. `pg-0067-cancellation-dispatch-management` 把 capability 提升至 v66。`ql3_run_manager` 只新增 dispatch SELECT 与四列 UPDATE:`status`、`version`、`next_attempt_at_ms`、`updated_at_ms`;没有 INSERT、DELETE、TRUNCATE、lease 字段 UPDATE 或 schema authority。
|
||||
10. Attempt active check 在已有 SERIALIZABLE 事务与 Run 行锁后执行普通 SELECT。PostgreSQL 的 `FOR KEY SHARE` 也隐含要求至少一列 UPDATE 权限;为行锁扩大 Run manager 的 Attempt UPDATE authority 被拒绝。并发终态变化由 Run 锁与 serializable ordering 收敛。
|
||||
11. 新 repository 留在现有 `cluster-postgres/run-management` 子域,协议留在现有 `cluster-admin/run-management` 子域。新增两个文件不会成为拆分 package 的理由;workspace 继续精确为 18 包。
|
||||
|
||||
## 被拒绝的替代方案
|
||||
|
||||
### 直接暴露数据库记录
|
||||
|
||||
拒绝。原始表包含 lease owner/token digest 等 capability-adjacent 字段,也没有逐请求 Policy、强认证、审计和响应 shape 验证。
|
||||
|
||||
### blocked 自动重试
|
||||
|
||||
拒绝。身份、PID 或协议不匹配不是瞬时可用性问题;自动循环可能向错误执行实例重复交付停止。
|
||||
|
||||
### 新建 cancellation-admin 服务或 package
|
||||
|
||||
拒绝。既有 Run management plane 已拥有完全相同的用户身份、Project Policy、mTLS、连接和生命周期边界。另建服务会增加低价值微包、端口、Secret 和部署成本。
|
||||
|
||||
### 给 Run manager 增加 RunAttempt UPDATE 权限
|
||||
|
||||
拒绝。该权限只为满足 PostgreSQL 行锁语法,而不是业务 mutation。SERIALIZABLE + Run lock + 普通读取足以表达合法顺序,不能为了实现细节扩大 authority。
|
||||
|
||||
## 资源、安全与部署影响
|
||||
|
||||
- Edge/Standalone package closure 不包含 `cluster-admin`、`cluster-postgres` 或 `pg`;14 个 Local Profile 预算不变化。
|
||||
- Cluster 复用既有 caller-driven management request,没有扫描 timer、后台队列、缓存、额外连接或空闲写入。
|
||||
- 每次 inspect/rearm 最多一个 5 秒 statement timeout 的 SERIALIZABLE 短事务;rearm 只在人工明确操作时写一条 RunEvent 和一条 audit。
|
||||
- response 与客户端都做 exact-shape 验证;未知字段、目标漂移、version/result/delay 漂移和 lease capability 泄漏失败关闭。
|
||||
|
||||
## 验证
|
||||
|
||||
- Repository 聚焦测试 `5/5`,service `6/6`,transport/client `12/12`;覆盖低敏 inspect、viewer/read 与 operator/stop 分权、exact replay、stale fence、失败审计和 secret-field tampering。
|
||||
- `cluster-postgres` 完整包 `339 pass / 0 fail / 3 conditional skip`;`cluster-admin` 完整包 `394 pass / 0 fail / 3 conditional skip`。
|
||||
- 完整 backend `1,487 pass / 0 fail / 2 conditional skip`;18-package clean build/test 退出 0。
|
||||
- package boundary、cluster dependency、Edge import、cluster deployment 四项审计零 finding;workspace 仍为 18 包,Cluster PostgreSQL 为 172 source/171 nested,根入口计数不变。
|
||||
- `14/14` Local artifact audit 通过:基础 Edge/Standalone `2,589,998 / 2,590,076` bytes,Application+AI `4,493,151 / 4,493,283` bytes,均不包含 PostgreSQL closure。
|
||||
- PostgreSQL 18.6 arm64 HA `144/144`:真实 `ql3_run_manager` 执行 blocked→inspect→rearm,验证 retry not-due、最终 production dispatch、同步 WAL、主库隔离与 standby promotion;timeline `1→2`,报告 SHA-256 `58f43327f426c286aaa1764aa6dd9f5963a462304716e09b933f326991442b8a`。
|
||||
|
||||
## 后续
|
||||
|
||||
私有 operator 协议已经闭合,但面向产品的聚合 blocked/availability 指标、告警和 UI 仍待实现。CloudNativePG live failover、多副本容量压力、固定 Linux x64/arm64 与物理 Edge 资源证据继续作为发布最终化门,不由单机 Docker HA 结果替代。
|
||||
Reference in New Issue
Block a user