Files
orbit/docs/reports/phase-3-application-resources.md

8.1 KiB
Raw Blame History

P3 应用级配额与跨命名空间回归

验证日期:2026-09-17。本阶段补齐应用共享的未终结任务上限、执行并发及开始速率,同步 HTTP、独立 Go SDK、CLI 和双命名空间示例。P3 业务键许可、公平性及可靠订阅,以及 P4–P7 仍未完成,持续目标保持进行中。

1. 交付范围

  • 应用配额接口:读取当前应用额度及用量、显式应用管理权限、CAS/幂等管理、同事务审计和事件、降额保留在途任务。
  • ApplicationResources 模型 与 000010 前向迁移:12 个持久化字段提供中文注释,SQL 同步 COMMENT,应用主键 BINARY(16),数据库外键仍为零,当前模型共 33 个。
  • 受理、计划生成、领取、Start、取消、Finish、安全重试及到期恢复共同维护应用计数,跨命名空间与队列共享。空轮询与失败受理不消耗计数,重复回执不重复计费。
  • 额度行与认证身份分离,统一按应用额度 → 队列 → 任务/尝试 → 许可顺序取锁;后台扫描跳过忙碌额度,应用停用后仍可释放到期尝试。
  • 管理 CLI 支持 --application-id 在已有启用应用下增加命名空间;应用管理权限必须显式 --resource-access,普通队列及 Worker 凭据不扩权。
  • 双命名空间 SDK 示例:第一侧受理,第二侧 APPLICATION_FULL,第一侧取消释放,第二侧原身份重报成功,取消收尾并按 CAS 恢复配置。

2. 环境和实际回归

macOS 本机,Go 1.27.1,Docker MySQL 8.4.10;服务进程与数据库仅监听回环地址。使用随机凭据及一次性数据库,测试结束删除测试容器,没有修改已有业务数据库。

执行入口:

make fmt test vet build
make integration

完整集成通过。测试分组的本次结果:

分组 结果
全部数据库集成(含模型、无外键、配额、计划、执行及竞争) PASS,68.475 秒
v9 应用计数回填与在途释放 PASS,3.94 秒
v7 无外键升级、索引及数据保留 PASS,3.85 秒
SDK Worker 连接、运行器、重试、取消和断线处理 PASS,78.509 秒
SDK 计划生命周期 PASS,含包开销 4.733 秒
SDK 队列资源控制 PASS,含包开销 4.456 秒
SDK 双命名空间应用配额 PASS,含包开销 1.401 秒
原有真实进程故障组 PASS,23.638 秒
十个可运行示例 全部通过

十个示例为 health、tasks、worker-protocol、worker、history、retry、schedules、cancellation、resources、application-resources。上述用时仅为回归耗时,不是吞吐或容量结论。未配置集成环境的普通 go test 会跳过外部数据库及进程用例,实际证据来自已执行的集成入口。

本轮发现原计划版本边界用例使用宿主机时钟等待,而服务按数据库时间判定。用例改为从 MySQL 时间建立边界并等待真实数据库时刻,保留原版本、触发身份和结束状态断言;完整数据库回归随后通过。

3. 配额与事务证据

数据库用例 覆盖:

  1. 普通队列凭据读取及管理应用额度被拒绝;显式授权后同应用另一个命名空间可读聚合额度,其他应用保持独立。
  2. 配置 CAS、同身份原快照重报、内容冲突;审计故障注入使配置、事件及幂等记录一起回滚,恢复后原身份可成功提交。
  3. 两个命名空间各自队列同时发起 16 次受理,上限为 3 时仅 3 次成功;满额原成功回执仍可核对。降额至 1 不删已有任务,逐项取消后重新受理。
  4. 队列已满和事件写入失败均不能泄漏应用额度;应用与队列计数同时回滚,原请求可以重报。
  5. 两个节点/命名空间争用应用并发 1,仅一个取得尝试;预占取消释放未开始额度,成功结果及重复 Finish 不重复释放。
  6. 预占后降低并发及开始速率,已有尝试保留;Start 事件故障回滚用量;原 Start ACK 重报不收费;未开始的预占跨窗口保留,不能被其他任务抢占。
  7. 明确失败重试不重复占用积压,已开始失联保留未知效果及未完成额度,未开始到期和待执行截止释放空间。应用停用不阻止后台回收执行额度。
  8. 定时计划遇到应用满额时保留未受理触发点,已生成的批次部分提交;释放空间后恢复同一原触发点,两级计数一致。
  9. 一个应用额度行被显式持锁时,另一应用的恢复仍能推进;缺失、停用或参数歧义的应用不能由初始化 CLI 创建新命名空间。

所有计数断言同时查询真实任务状态进行核对,不只断言接口里的同一计数字段。

4. 迁移和无外键

应用额度升级测试 在隔离库建立有效任务、尝试、Worker 会话和许可,然后还原为 v9 结构再运行正式迁移:

  • 同一应用两个命名空间包含 WAITING、LEASED、RUNNING、NEEDS_REVIEW 和已成功任务,回填为 unfinished=4、active=2、pending=1;成功任务排除在外。
  • 空应用三个用量均为零,配置默认值、版本与空窗口正确。
  • 历史任务状态及版本不变;重复执行迁移不重算或覆盖当前计数。
  • 迁移前已存在的预占取消和运行尝试完成后,共享用量正确变为 unfinished=2、active=0、pending=0。

v4 升级继续核对冻结策略、未知标记及应用未完成数。v7 无外键升级仍移除全部 70 个历史外键,已有 325 条索引列定义保留;新应用额度表自身主键另计。错误队列归属、错误会话关系及手工外键漂移继续被拒绝。

5. SDK 与进程验证

SDK 集成用例 通过实际 HTTP 验证两个命名空间共享配置、普通队列管理员无应用权限、跨命名空间幂等键空间独立、错误字段及应用归属覆盖被拒绝。第二侧收到 HTTP 429 / APPLICATION_FULL / Retry-After: 1;第一侧释放后,原键提交成功,最终三个用量为零。

示例实际输出:

cross_namespace_backpressure=APPLICATION_FULL http=429
same_identity_retry_accepted=true
unfinished=0 active=0 pending_starts=0

原有服务 ACK 丢失接管、Worker 强杀后未知核查、计划强杀补跑和队列背压进程用例同步通过。

最后定向回归新增的额度泄漏断言与应用强杀场景也通过:数据库应用配额九组场景 10.24 秒(含包开销 11.572 秒),SDK 应用配额 0.15 秒,完整示例再次通过;TestIntegrationWorkerProcessApplicationBackpressure 0.14 秒(含包开销 1.818 秒)。该场景强杀并 Wait 确认旧服务退出,再启动不同 node_id:共享上限和未完成计数保留,原受理回执可重放,另一个命名空间继续被全局满额拒绝,原任务取消后才能用被拒原键受理。这项证明应用受理额度跨进程持久化,不将它扩大为全部数据库故障模型或开始速率窗口的进程验收。

文档校验通过 320 个本地链接及 26 个 JSON 示例;269 个直接声明的持久化字段全部有中文注释。

6. 当前边界

  • 共享配额限于同一 MySQL 主库。单个应用的额度行是串行化点,必须在生产容量阶段测锁等待、吞吐、续租与恢复延迟;没有宣称百万租户容量或跨库原子配额。
  • 开始限流为固定一秒窗口,允许边界突发;控制的是平台授权次数,不是处理器内部业务请求。
  • 停止旧写入节点后迁移再启动新版,不能与不维护应用用量的旧节点混跑。大表回填和混合版本在线升级未验收。
  • 数据库关联依靠服务端事务,没有外键;直接 SQL 修改归属或删除额度记录不属于支持的业务操作。
  • 本轮为单数据库、多服务进程及故障注入验证;数据库复制切换、跨故障域网络分区、备份恢复、实际 RPO/RTO 和峰值容量仍在 P6。