feat: add report material workflows and gateway safeguards
This commit is contained in:
@@ -234,7 +234,8 @@
|
||||
7. Gateway 必须实现真实 CMPP Submit,包括短信内容编码、长短信拆分、RegisteredDelivery、serviceId、srcId、destTerminalId、msgFmt、feeType/feeCode 等字段映射。
|
||||
8. Gateway 必须消费 NestJS 投递的 `SubmitCommand` 队列或等价内部接口;提交成功、提交失败、超时均必须回传 `SubmitResult`,不得只停留在 API 侧入队。
|
||||
9. Gateway 必须按通道连接和窗口容量控制并发,处理窗口满、SMSC 慢响应、sequence 回绕、连接断开时的在途消息状态。
|
||||
10. Gateway 不承担业务审核、计费、签名报备、通道组路由、黑名单或敏感词判断;这些由 NestJS 完成,Gateway 只执行已授权通道提交与协议事件回传。
|
||||
10. Gateway 必须对每个物理通道执行 Redis 分布式 TPS 限速。`SmsChannel.rateLimitPerSecond` 是单通道上限,不是平台总上限;同一通道被多个通道组或多个 Gateway 实例使用时共享同一额度,不同通道独立计数。通道连接命令下发的配置值是最终上限,提交命令携带的值只能进一步降低、不能放大该上限。超流速消息必须继续保留在 Redis Stream pending 中等待可用时隙,不能因等待直接标记发送失败;Gateway 重启后仍可由 consumer group 恢复。worker 必须并发处理一个读取批次,让不同通道独立等待,不能因低 TPS 通道造成其他通道队头阻塞;单通道实际并发仍由 Redis 限速和 CMPP 窗口共同约束。
|
||||
11. Gateway 不承担业务审核、计费、签名报备、通道组路由、黑名单或敏感词判断;这些由 NestJS 完成,Gateway 只执行已授权通道提交与协议事件回传。
|
||||
|
||||
#### 4.8.2 下游客户 CMPP 接入能力
|
||||
|
||||
@@ -278,7 +279,8 @@
|
||||
- 已实现 SubmitCommand 在途恢复第一版:Go Gateway submit worker 在消费新消息前会对 Redis Stream consumer group 中空闲超过阈值的 pending 命令执行 `XAUTOCLAIM`,重新提交并按正常成功路径 ack,避免 Gateway 重启后命令永久滞留在 PEL。
|
||||
- 已实现上游连接断开时的 pending submit 状态补偿第一版:如果某条上游 CMPP 连接在收到 submit resp 前断开,Gateway 会立即唤醒该连接上等待中的 pending submit,请求返回 `timeout/CONNECTION_LOST`,由 NestJS 进入既有补发或释放冻结逻辑,不再只依赖固定超时。
|
||||
- 已实现“上游可能已受理但 submit resp 丢失”场景的保守补偿第一版:Gateway 在 receipt 事件中补充手机号;NestJS 对无法按 `messageId/gatewayMessageId` 精确命中的回执,只在“同通道、同手机号、72 小时窗口内、且仅存在 1 条 `timeout + gatewayMessageId=null` 的 submit 记录”时才回填并接收该回执,避免误绑到其他短信。
|
||||
- 已实现 SubmitCommand 死信治理第一版:Go Gateway 对多次处理仍失败的 `SubmitCommand` 不再无限滞留在 PEL,而是按阈值写入 NestJS 真实 `GatewaySubmitDeadLetter` 表;运营端后端接口可分页查询死信,并支持人工将原始 `SubmitCommand` 重新写回 Redis Stream。
|
||||
- 已实现 Gateway 提交异常治理:Go Gateway 对多次处理仍失败的 `SubmitCommand` 不再无限滞留在 PEL,而是按阈值写入 NestJS 真实 `GatewaySubmitDeadLetter` 表(数据库表名和内部接口保留技术兼容名,页面统一称“Gateway提交异常”)。运营端 `/admin/gateway-submit-exceptions` 提供真实分页、筛选、汇总、脱敏详情和单条重新入队;原始 payload、密码、密钥不得返回浏览器。重新入队必须要求近期认证、填写原因、勾选“已确认上游未受理”,并校验短信尚未 accepted/submitted/delivered/unknown、通道 active 且 connected、人工次数小于 3;服务端以 pending 到 requeueing 的原子状态抢占防止重复点击,成功写回 Redis Stream 后记录操作人、原因、Stream ID 和时间。收到后续 SubmitResult 时必须将对应异常记录闭环为 resolved。
|
||||
- 已实现 Gateway 通道级 Redis 限速:NestJS 入队前保留业务层通道限速,Go Gateway 在真正调用上游 Submit 前再次按通道 ID 预约发送时隙;连接命令把权威 TPS 写入 Redis,提交按权威值与消息值的较小者执行。普通 Stream 消息在等待期间不 ACK、不转失败,多实例共同使用同一限速状态;worker 对同批消息并发调度,低 TPS 通道等待不阻塞其他通道。
|
||||
- 已实现客户侧下游投递重试第二版:客户系统负责断线后重连;平台在客户离线或投递失败时把 Deliver Receipt/上行 Deliver 保留在 `CmppDownstreamDelivery`,客户 bind 成功后立即拉取 pending,且 Gateway 会对当前在线账号周期补投;超过重试上限后转 `failed` 并写失败审计。
|
||||
- 已实现下游投递失败审计与人工重投第一版:运营端后端与页面可分页查看 `CmppDownstreamDelivery` 的 pending/awaiting_ack/failed/unconfirmed/rejected/delivered 记录,支持按状态、类型、应用和关键字筛选,并可对非 `awaiting_ack` 记录执行人工重投,真实调用 Gateway `/downstream/receipt` 或 `/downstream/uplink`。主记录必须分开保存自动重试次数 `retryCount`、人工重投次数 `manualRetryCount` 和最近人工重投时间 `lastRetriedAt`,操作日志保留重投前状态与自动重试次数。
|
||||
- 已实现下游投递批量重投第一版:运营端可在当前页勾选多条 `pending/failed` 下游投递记录,调用真实批量接口逐条重投并返回成功/失败汇总,不允许用前端循环假装成功。
|
||||
@@ -315,7 +317,7 @@
|
||||
- 客户侧 Deliver 重投当前已经具备账号级周期恢复、退避、Redis token 租约锁和控制面状态观测;恢复状态已同步到 NestJS 持久化审计表并进入运营端独立页面,且具备第一版失败分类分析和多 Gateway 抢占协调。
|
||||
- 普通上行匹配已覆盖 messageId、接入号、手机号时间窗口和共享接入号多候选人工认领;后续仍需补更复杂的批量认领、认领规则推荐和认领准确率指标。
|
||||
- 长短信分片当前已具备真实分片提交/回执/补偿审计,运营端短信详情可查看 `SmsMessageSegmentAudit`;后续仍需补“按单个分片自动重投”和分片级人工补偿操作。
|
||||
- 多连接窗口当前覆盖单进程内连接池和窗口满等待;在途恢复当前覆盖 Redis Stream pending claim、连接断开时的 pending submit 唤醒、receipt 驱动的保守唯一候选补偿、SubmitCommand 死信入库/人工重入队第一版,以及下游客户在线时的周期补投、Gateway 重启后的恢复候选扫描、账号级 Redis token 租约锁/退避/状态观测、恢复状态入库/运营端可视化;尚未实现连接级状态持久化、窗口指标回写、死信后台自动重试策略、长恢复任务锁续租,以及“上游已受理但 submit resp 丢失”场景的强确认或完整幂等补偿。
|
||||
- 多连接窗口当前覆盖单进程内连接池和窗口满等待;在途恢复当前覆盖 Redis Stream pending claim、连接断开时的 pending submit 唤醒、receipt 驱动的保守唯一候选补偿、Gateway 提交异常转存/安全人工重新入队,以及下游客户在线时的周期补投、Gateway 重启后的恢复候选扫描、账号级 Redis token 租约锁/退避/状态观测、恢复状态入库/运营端可视化;尚未实现连接级状态持久化、窗口指标回写、提交异常后台自动重试策略、长恢复任务锁续租,以及“上游已受理但 submit resp 丢失”场景的强确认或完整幂等补偿。
|
||||
|
||||
基于当前真实代码,CMPP 端到端链路剩余缺口可以明确收敛为以下几类:
|
||||
|
||||
@@ -698,6 +700,8 @@
|
||||
9. 按企业应用绑定的对应运营商通道组执行路由:通道组只能是移动、联通、电信之一,发送时必须同时满足路由规则运营商、通道组运营商、通道组明细 carrier 与号码识别运营商一致;再校验通道本体 carrier 为对应运营商或三网;最后先匹配省网通道,再匹配全国通道,不得直接绑定或 fallback 到非授权单通道。
|
||||
10. 过滤业务 disabled、连接离线、认证失败、心跳超时或无可用连接数的通道。
|
||||
11. 通过通道限速器控制 TPS;优先队列不得突破通道配置的供应商 TPS 和连接窗口上限。
|
||||
- TPS 按物理通道独立计数,不是整个平台共享一个总额度。例如通道 A、B 均配置 100 TPS 时,各自最多 100 TPS,平台理论合计为 200 TPS。
|
||||
- 同一物理通道被多个通道组使用时,共享 `SmsChannel.rateLimitPerSecond` 的同一额度;通道组成员不提供单独流速配置,避免多个组并发使用同一供应商账号时重复计算额度。
|
||||
12. 调用 Gateway Adapter 提交短信。
|
||||
13. 写入 submit 状态。
|
||||
14. Submit rejected、submit timeout、Gateway 连接断开或未提交成功、receipt failed 等场景按通道组策略补发到下一可用全国通道;unknown、超过 72 小时、超过通道组补发时间上限或关闭补发时不再补发。
|
||||
@@ -1473,3 +1477,12 @@
|
||||
|
||||
然后按计划逐步实现。每完成一步都要运行构建或测试,并更新文档。
|
||||
```
|
||||
|
||||
### 2026-07-15 签名与引流资料批量导入、通道映射及统一报备
|
||||
|
||||
1. 运营端在“报备任务”下提供“待报备资料”工作台。WPS 在线表格须先由用户另存为 `.xlsx`,系统读取真实工作簿、工作表、表头、单元格和内嵌图片;原始文件及拆出的图片写入 MinIO,导入批次、映射和业务资料写入 PostgreSQL,不支持用 CSV、前端静态数组或浏览器本地存储冒充图片导入。
|
||||
2. 导入分为“解析预览”和“确认入库”两步。用户可指定企业、企业应用、资料类型、表头行数、数据起始行并复用映射方案;每个源列可映射到签名名称、用途、所属签名、站点名称、URL、备注或报备字段库中的动态字段,同时配置文本/图片/文件、必填和转换规则。源文件字段名称和顺序不固定,映射方案必须可持久化复用。
|
||||
3. 导入和业务页面的新建/修改只将已审核签名或引流信息标记为待报备,并递增材料版本;不得在每次导入后自动创建通道报备任务。运营人员可跨签名、跨引流信息勾选资料,一次创建统一报备批次。
|
||||
4. 创建批次时按每条资料所属企业应用的当前生效路由规则展开所有通道;一个签名走多个通道时,必须为每个通道创建或重置独立报备任务并生成一份该通道的 `.xlsx`。无生效路由、通道未配置字段或缺少通道必填资料时,该资料继续保留在待报备池,任务进入“资料待补充”,不得伪装为已完成。
|
||||
5. 通道“配置签名报备字段”和“配置引流信息字段”弹窗使用字段池,按资料类型分别配置。每列包含标准字段、通道导出表头、列顺序、必填、说明、列宽、文本转换、缺省值以及图片宽高;导出表头和列顺序必须严格使用通道配置,不受导入表格原始名称和顺序影响。
|
||||
6. 通道导出文件必须为 WPS/Excel 可打开的 `.xlsx`,图片直接内嵌到对应单元格区域,而不是仅写 MinIO URL 或本地路径。批次保留所选材料版本快照、通道文件、行号和通道任务关联,可从最近批次直接下载每个通道文件。
|
||||
|
||||
Reference in New Issue
Block a user