Files
orbit/docs/reports/phase-3-batch-tasks.md

6.9 KiB
Raw Blame History

P3 批量任务受理回归

验证日期:2026-09-17。本阶段增加批量受理、SDK及部分补交场景;不代表P3或全平台验收完成。完整集成已通过,下面记录实际覆盖范围与剩余边界。

1. 实现与证据入口

  • 服务契约:最多32项,逐项独立事务与幂等,ACCEPTED/REJECTED/UNKNOWN/NOT_ATTEMPTED四类结果。未知数据库结果或凭据失效后停止余项,上下文结束保留已确认前项。
  • HTTP入口:POST /v1/tasks:batch,全体正文严格解析后才受理,每项正文幂等键,总请求512 KiB。完整响应使用HTTP200,逐项标记结果。
  • 独立SDK:SubmitTasks及中文字段说明,不自动生成身份、拆批或重试;校验返回数量、顺序、状态与回执归属。
  • 运行示例:两项受理、一项满额,原键核对后释放配额,仅补交被拒项并取消收尾。
  • 接口手册、场景说明、开发计划 同步维护。

不增加数据库模型或迁移,平台仍为35个实体、289个中文注释持久化字段;不增加外键、级联或SDK数据库依赖。

2. 验证环境与命令

macOS、Go1.27.1、Docker单实例MySQL8.4.10。使用一次性数据库、随机测试凭据及回环端口,结束后自动删除,不修改已有业务库。

make fmt test vet build
make integration

普通测试没有数据库环境时会跳过Integration;数据库/HTTP/进程证据来自真实集成入口。并发修复另在一次性数据库重复执行:

go test -race -count=20 \
  -run '^TestIntegrationTaskBatch/concurrent_replay_and_shared_application_backpressure$' \
  -v ./internal/storage/mysql

该定向命令要求 ORBIT_TEST_MYSQL_DSN 指向一次性数据库;正式完整脚本会自动准备隔离环境。

验证组 实际结果
fmt / race / vet / build 已通过
定向批量MySQL六组场景 PASS,5.559秒,含包开销
真实HTTP丢失批量响应及SDK补交 PASS,1.458秒,含包开销
完整批量示例 已通过,unfinished=0
同键并发与共享配额20次重复 PASS,10.110秒;每轮8个调用者
全量MySQL集成 PASS,94.874秒
SDK Worker完整组 PASS,88.099秒
SDK调度 / 队列资源 / 批量受理 PASS,5.640 / 4.474 / 1.361秒
SDK订阅管理 / 事件消费 PASS,33.508 / 51.852秒
Inbox六组真实数据库/消费者故障 PASS,35.783秒
SDK应用配额 PASS,1.426秒
九项节点/Worker进程故障 PASS,69.057秒;连同Inbox消费者共十项真实进程故障
全部运行示例 15个核心SDK示例 + 1个独立Inbox示例通过

上述完整脚本正常退出,状态码0;没有以尚在运行的日志推断完成。文档链接与JSON代码块核对通过,核心SDK依赖检查未包含服务端模型或MySQL驱动。以上是单次回归耗时,不是吞吐或性能指标。

3. 事务、权限与配额

数据库回归 实际验证:

  1. 有效/参数无效/不存在队列/队列满额混合批次,每项结果独立;数据库仅有两份任务、受理幂等、事件及审计。
  2. 单项与批量共用原始回执;取消后重报仍返回原受理版本,满额也不阻止已提交身份核对。释放配额后原失败身份受理成功,同键不同内容仍冲突。
  3. 跨命名空间队列与队列权限拒绝;即使已有回执也不能绕过当前队列范围。
  4. 第一项提交后撤销凭据,第二项重新认证拒绝,第三项未尝试;只有第一项任务存在。
  5. 第一项提交后取消请求上下文,后缀未写入;恢复后整批原键重报,首项去重、后缀受理。
  6. 真实审计触发器故障使新项事务回滚,任务/幂等/事件/配额不残留;既有已受理项保留。接口保守返回UNKNOWN,修复故障后原身份补交成功。
  7. 八个调用者同时重报四个相同身份,应用上限3;前三个稳定任务ID、仅三次新受理,第四项APPLICATION_FULL,另一命名空间也受共享额度限制。

单元及HTTP边界还覆盖整批非法键/重复键/超量、全项参数无效时仍认证、未知字段/大小写别名/重复JSON键/null、超大正文、禁止整批幂等头、精确整数、不完整或矛盾的SDK回执,以及上下文和内部错误不泄露细节。

4. 并发回归发现与修复

最初同键并发满额场景实际出现MySQL 1213死锁,API按既有保守规则报告UNKNOWN。测试没有将UNKNOWN改判成功,也没有通过放宽断言隐藏问题。

任务提交原来先抢占幂等唯一键,再等待应用额度锁。在满额回滚和同键INSERT竞争中触发锁冲突。本轮调整为:认证 → 应用额度锁 → 提交幂等身份 → 队列 → 任务/事件/审计。取得应用锁时不检查或扣减额度;读取已有回执仍在配额检查之前。

提取只在应用锁已持有时使用的队列锁辅助函数,避免重复查询应用锁。每项事务结束后释放全部锁,整个批次不持有跨项锁。没有新增外部锁服务、数据库外键或盲目重放事务。当前场景通过不表示全部MySQL负载不再可能死锁;其他未知数据库错误仍必须原身份核对。

5. 真实HTTP故障与示例

SDK集成 启动真实HTTP代理:先读完平台已经生成的受理响应,再强制关闭客户端连接、丢弃响应。SDK返回网络错误,未自动补发。再次用原键/原参数请求,两项返回同一任务且deduplicated=true,第三项保持QUEUE_FULL;查询仅存在两行任务。取消一项后只补交原第三项,受理成功。

完整示例输出:

accepted=2 rejected=1 code=QUEUE_FULL
replayed=2 same_task_ids=true
retried_items=1 same_identity=true accepted=true
queue=<实际ID> paused=true unfinished=0

这验证受理与HTTP回执恢复,不等同于Worker业务效果恰好一次,也不是业务事务Outbox。任务、队列和审计保留,无硬删除。

6. 兼容与尚未验收范围

  • 无数据库迁移变更;批量与单项受理的身份、策略、事件和审计相同。新SDK调用旧节点返回404,不静默降级。
  • 单项与批量均使用调整后的锁顺序。部署应统一升级写入节点;未做新旧二进制混合压力或滚动发布验收。
  • 批次逐项串行,8秒HTTP预算不保证每次32项全部尝试;大参数回执不重复携带原输入。调用方必须处理部分提交和响应全丢。
  • 本轮为本机单MySQL正确性验证,未验证数据库故障切换、跨区域网络、百万租户容量或生产RPO/RTO。
  • P3仍缺独立任务人工核查/重试、业务键及时间筛选、事务Outbox示例;P4–P7仍按原目标推进。