96 lines
6.9 KiB
Markdown
96 lines
6.9 KiB
Markdown
# P3 批量任务受理回归
|
||
|
||
验证日期:2026-09-17。本阶段增加批量受理、SDK及部分补交场景;不代表P3或全平台验收完成。完整集成已通过,下面记录实际覆盖范围与剩余边界。
|
||
|
||
## 1. 实现与证据入口
|
||
|
||
- [服务契约](../../pulse/service/batch.go):最多32项,逐项独立事务与幂等,ACCEPTED/REJECTED/UNKNOWN/NOT_ATTEMPTED四类结果。未知数据库结果或凭据失效后停止余项,上下文结束保留已确认前项。
|
||
- [HTTP入口](../../internal/transport/httpserver/tasks.go):`POST /v1/tasks:batch`,全体正文严格解析后才受理,每项正文幂等键,总请求512 KiB。完整响应使用HTTP200,逐项标记结果。
|
||
- [独立SDK](../../sdk/go/batch.go):SubmitTasks及中文字段说明,不自动生成身份、拆批或重试;校验返回数量、顺序、状态与回执归属。
|
||
- [运行示例](../../examples/batch/main.go):两项受理、一项满额,原键核对后释放配额,仅补交被拒项并取消收尾。
|
||
- [接口手册](../api/batch-tasks.md)、[场景说明](../examples/batch.md)、[开发计划](../08-development-plan.md) 同步维护。
|
||
|
||
不增加数据库模型或迁移,平台仍为35个实体、289个中文注释持久化字段;不增加外键、级联或SDK数据库依赖。
|
||
|
||
## 2. 验证环境与命令
|
||
|
||
macOS、Go1.27.1、Docker单实例MySQL8.4.10。使用一次性数据库、随机测试凭据及回环端口,结束后自动删除,不修改已有业务库。
|
||
|
||
```sh
|
||
make fmt test vet build
|
||
make integration
|
||
```
|
||
|
||
普通测试没有数据库环境时会跳过Integration;数据库/HTTP/进程证据来自真实集成入口。并发修复另在一次性数据库重复执行:
|
||
|
||
```sh
|
||
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. 事务、权限与配额
|
||
|
||
[数据库回归](../../internal/storage/mysql/task_batch_integration_test.go) 实际验证:
|
||
|
||
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集成](../../sdk/go/batch_integration_test.go) 启动真实HTTP代理:先读完平台已经生成的受理响应,再强制关闭客户端连接、丢弃响应。SDK返回网络错误,未自动补发。再次用原键/原参数请求,两项返回同一任务且deduplicated=true,第三项保持QUEUE_FULL;查询仅存在两行任务。取消一项后只补交原第三项,受理成功。
|
||
|
||
完整示例输出:
|
||
|
||
```text
|
||
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仍按原目标推进。
|