feat: add application queue priority routing

This commit is contained in:
hectorzhao
2026-07-07 14:49:10 +08:00
parent 72f2c010ce
commit 4c8f7dd73f
17 changed files with 392 additions and 46 deletions
+60 -3
View File
@@ -16,7 +16,7 @@
| --- | --- |
| 租户 | `tenant-a` 正常企业,`tenant-b` 用于租户隔离验证。 |
| 用户 | 客户端企业管理员、客户端普通用户、运营管理员、运营审核员。 |
| 短信应用 | `app-a`,状态 active,日限额开启,模板不匹配策略分别准备 reject/manual_review/allow 三组。 |
| 短信应用 | `app-a`,状态 active,日限额开启,模板不匹配策略分别准备 reject/manual_review/allow 三组;另准备普通队列应用 `app-normal` 和优先队列应用 `app-priority`。 |
| 签名 | `【测试签名】`,审核通过且报备通过;另准备待审核、驳回、报备失败签名。 |
| 模板 | 验证码模板 `验证码为 ${code}`,营销模板 `尊敬的${name},优惠活动开始`,分别准备草稿、待审核、通过、驳回。 |
| 通道 | active CMPP 通道、disabled 通道、备用通道;通道组包含主备优先级。 |
@@ -34,6 +34,7 @@
| 企业认证闭环 | 客户提交资料、运营审核、客户查看状态、驳回重提、通过后才允许使用受限发送能力、日志可追溯。 |
| 客户管理闭环 | 客户创建、编辑、启停、认证、额度/余额、客户下应用/签名/模板/发送记录联动、租户隔离、日志可追溯。 |
| 短信应用闭环 | 创建、启停、删除、密钥重置、IP 白名单、模板不匹配策略、变更后对发送实时生效、日志可追溯。 |
| 应用队列等级闭环 | 客户端和运营端创建/编辑应用时保存普通/优先队列配置;发送入队按应用队列等级分流;优先队列在不绕过业务校验和通道限速的前提下插队消费。 |
| 签名闭环 | 创建、材料、审核、删除、报备状态变化、发送可用性校验、历史任务不受错误覆盖、日志可追溯。 |
| 引流信息闭环 | 字段配置、客户填写、删除字段或删除客户引流信息、报备材料影响、发送阻断或审核原因可见。 |
| 模板闭环 | 单变量、多变量、审核、删除、变量缺失/多传/格式异常、计费预估、发送可用性校验。 |
@@ -65,12 +66,12 @@
- 优先级:P1
- 前置条件:企业管理员已登录。
- 步骤:
1. 创建短信应用,填写名称、场景、回调地址、IP 白名单、日限额。
1. 创建短信应用,填写名称、场景、回调地址、IP 白名单、日限额,并选择发送队列等级
2. 查询应用列表和详情。
3. 执行应用密钥重置。
- 预期结果:
- 应用创建成功,状态为 active。
- IP 白名单、日限额、模板不匹配策略保存正确
- IP 白名单、日限额、模板不匹配策略和发送队列等级保存正确,刷新后仍来自真实 API/数据库
- 密钥重置后旧密钥不可见,新密钥或密钥摘要更新。
- 生成操作日志。
@@ -470,6 +471,23 @@
- 删除连接调用真实后端或 Gateway 接口,连接状态刷新并写系统日志。
- CMPP 参数来源于真实应用/通道配置,一键复制内容与 API 返回一致。
### TC-ADMIN-018A 企业应用新增表单企业选择与队列等级
- 优先级:P0
- 前置条件:存在至少两个真实企业,运营管理员已登录,通道组基础数据可用。
- 步骤:
1. 打开运营端企业应用管理,点击新增短信应用。
2. 在第一步选择企业下拉框中查看企业选项、加载态和空态。
3. 选择企业后进入应用参数表单。
4. 配置应用名称、客户单价、IP 白名单、发送队列等级、移动/联通/电信通道组后保存。
5. 刷新列表并打开编辑页。
- 预期结果:
- 企业选择使用项目通用 Select/下拉控件,样式、禁用态、错误态与系统其他下拉一致。
- 企业选项来自真实企业 API,不使用静态数组、mock 或 localStorage。
- 请求体包含 tenantId、queuePriority、客户单价、IP 白名单和通道组绑定。
- 后端真实保存应用队列等级,刷新列表和编辑页后仍显示正确。
- 不选择任何通道组或缺少必填字段时不能保存,并显示可读提示。
### TC-ADMIN-019 通道连接日志展示
- 优先级:P1
@@ -960,6 +978,22 @@
- 第二条记录历史或被幂等处理。
- 不重复扣费或重复变更最终状态。
### TC-SEND-021 优先队列插队发送
- 优先级:P0
- 前置条件:存在普通队列应用 `app-normal` 和优先队列应用 `app-priority`;两者企业状态、应用状态、签名、模板、报备、余额、通道组、通道连接均可用;Redis/BullMQ 使用真实本地服务。
- 步骤:
1. 使用 `app-normal` 连续提交一批普通队列短信,使普通队列形成可观察积压。
2. 在普通队列积压未清空时,使用 `app-priority` 提交少量优先队列短信。
3. 观察数据库 message_record、BullMQ job、Send Worker 日志、submit trace 和 Gateway SubmitCommand 顺序。
4. 等待两类消息处理完成。
- 预期结果:
- 普通队列和优先队列消息均写入真实数据库,记录包含 queuePriority 或等价可追踪字段。
- 优先队列消息在普通队列已有积压时更早被 Send Worker 消费并提交 Gateway。
- 优先队列不绕过模板/签名/报备/余额/风控/通道组路由/通道限速/Gateway 连接校验。
- 普通队列后续能继续恢复消费,不出现永久积压或重复提交。
- trace 中可区分队列等级、入队时间、消费时间和 submit 顺序。
## 10. 契约与队列用例
### TC-CONTRACT-001 SubmitCommand Schema 校验
@@ -986,6 +1020,16 @@
- 步骤:运行 `npm run spike:contracts`
- 预期结果:`uplink-event.json` 通过 schema 校验。
### TC-CONTRACT-005 SubmitCommand 队列等级字段校验
- 优先级:P0
- 前置条件:SubmitCommand 契约已扩展 queuePriority、priority 或 queueName 字段。
- 步骤:运行 `npm run spike:contracts`
- 预期结果:
- SubmitCommand 示例覆盖普通队列和优先队列。
- schema 明确允许的队列等级取值,不接受未知等级。
- NestJS 生产者和 Gateway/Worker 消费者使用同一字段语义。
## 11. 端到端 Smoke 用例
### TC-E2E-001 核心发送闭环
@@ -1083,6 +1127,19 @@
- 无重复最终状态。
- 错误率满足阶段 0/8 性能报告要求。
### TC-PERF-003 混合优先级队列 Smoke
- 优先级:P0
- 前置条件:Redis/BullMQ 可用,准备普通队列和优先队列应用。
- 步骤:
1. 先提交一批普通队列消息制造积压。
2. 再提交优先队列消息。
3. 持续提交少量优先队列消息,同时观察普通队列恢复。
- 预期结果:
- 优先队列消息消费延迟明显低于已有普通队列积压。
- 普通队列不会被永久饿死。
- 端到端吞吐仍满足第一版性能 smoke 口径。
## 14. 业务闭环补充用例
### TC-CERT-001 企业认证资料提交