Files
lislgosms/docs/refactoring/r0-responsibility-index.md

145 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# R0 大文件职责与副作用索引
更新日期:2026-07-30
基线提交:`0af671b4ed4713912e703defd08791f164d4eb25`
## 1. 使用方式
本索引是后续拆分版本的行为地图,不是目标架构。开始任何 R1~R11 拆分前,必须:
1. 重新核对 Git 与部署基线,不能直接沿用本文提交号。
2. 找到目标方法所属的职责组、调用者、数据表和副作用。
3. 先运行该职责组的特征测试,再移动代码。
4. 保留原门面、公开方法、事务边界、幂等键和消息结构。
5. 如果实际代码与本文不一致,先更新索引再开始拆分。
## 2. 核心文件总览
| 文件 | 稳定门面 | 直接调用者 | 主要外部副作用 | 拆分优先级 |
|---|---|---|---|---|
| `api/src/send-chain/send-chain.service.ts` | `SendChainService` | Admin/Client SendChain Controller、GatewayEvents、RiskReview、Operations、OpenAPI | PostgreSQL、Redis Stream、Gateway 控制 API、账务与下游回执 | 最高 |
| `gateway/internal/inbound/server.go` | `inbound.Server` | Gateway 启动入口、控制面 | CMPP TCP、NestJS Gateway API、Redis 在线状态、ACK 定时器 | 最高 |
| `gateway/internal/upstream/manager.go` | `upstream.Manager` | Submit Worker、控制面 | 供应商 CMPP TCP、连接池、重连、回执和上行事件 | 最高 |
| `api/src/channels/channels.service.ts` | `ChannelsService` | Channels Controller、Report/SmsConfig 间接调用 | PostgreSQL、Gateway 连接控制、导入导出文件 | 高 |
| `api/src/sms-config/sms-config.service.ts` | `SmsConfigService` | Admin/Client SmsConfig Controller、GatewayEvents | PostgreSQL、Gateway 下游连接状态、审核日志 | 高 |
| `api/src/operations/operations.service.ts` | `OperationsService` | Admin/Client Operations Controller | PostgreSQL 聚合查询、CSV 导出、恢复控制 | 中高 |
| `src/api/adminApi.ts` | `adminApi` | 运营端页面和组件 | HTTP、文件上传下载、认证失败跳转 | 中高 |
| `api/src/report-materials/report-materials.service.ts` | `ReportMaterialsService` | ReportMaterials Controller | PostgreSQL、XLSX/CSV、MinIO/FileObject | 中高 |
| `src/styles/global.css` | 全局 class 名和 CSS 变量 | 全部页面 | 全局级联、响应式覆盖 | 高 |
## 3. SendChainService
### 3.1 公开职责组
| 职责组 | 公开入口(同组方法不得在一次拆分中漏项) | 主要表 | 队列/外部调用 | 不变量 |
|---|---|---|---|---|
| 客户批量发送 | 创建、预览导入、确认导入、取消、任务/号码分页 | `SmsBatchTask``SmsMessageRecord``SmsSendTask` | Redis 任务队列 | 去重、非法号码不计费、任务进度与真实记录一致 |
| HTTP/OpenAPI 发送 | API 请求受理、查询请求结果 | `SmsApiRequest``SmsMessageRecord` | Redis 任务队列 | 请求幂等、签名模板校验、同步错误不进入计费 |
| CMPP 入站 | 鉴权、Submit、长短信分片、重启恢复 | `CmppInboundLongMessage``SmsBatchTask``SmsMessageRecord` | 下游 SubmitResp/Deliver | 一个目标号码一条真实记录;原 `Msg_Id` 可恢复;冲突分片拒绝 |
| 审核恢复 | 审核通过/驳回、聚合任务展开 | `SmsSendTask``SmsMessageRecord` | Redis 任务队列、下游 Deliver | 每条消息只恢复一次;驳回必须释放冻结 |
| 路由与提交 | 入队、选择通道、创建提交记录 | `ChannelRouteRule``SmsChannel``SmsSubmitRecord` | `gateway.submit.commands` | 运营商/省份快照;仅走已报备通道;重试不重复扣费 |
| SubmitResult | 接收分片/聚合结果、提交异常重排 | `SmsSubmitRecord``SmsMessageRecord``GatewaySubmitDeadLetter` | Redis 重排 | 优先按 `submitId`;模糊匹配必须拒绝;相同幂等键恢复 |
| 最终回执 | 回执持久化、匹配、分片聚合、补发 | `UpstreamReceiptInbox``SmsReceiptRecord``SmsMessageSegmentAudit` | 重试提交、下游 Deliver | terminal 状态不可被旧事件降级;并发失败只产生一次补发 |
| 账务 | 冻结、扣费、释放、退款 | `SmsBillingRecord``AccountTransaction` | PostgreSQL 事务锁 | 同一业务键只记账一次;失败/拒绝路径释放或退款 |
| 下游投递 | 创建 Deliver、ACK、人工重排、超时扫描 | `CmppDownstreamDelivery``CmppDownstreamDeliveryAttempt` | Gateway control API、HTTP webhook | `Result=0` 且非零 `Msg_Id` 才是业务 ACK;并发重排只执行一次 |
| 上行短信 | 保存、候选匹配、人工认领 | `SmsUplinkMessage``SmsUplinkMatchCandidate` | 下游 Deliver/Webhook | 共享接入号歧义不得自动错配 |
| 恢复与扫描 | 定时任务、过期回执、长短信恢复、恢复状态 | 多表 | Redis/Gateway | 扫描必须可重复;抢占超时可恢复;不得覆盖已完成状态 |
### 3.2 事务、锁与幂等边界
- 顶层发送用例持有 Prisma 事务;未来子服务只能接收同一个 `TransactionClient`
- 定时任务、补发、下游人工重排使用数据库原子抢占;禁止改回“先查再写”。
- `SmsSubmitRecord``SmsBillingRecord``CmppDownstreamDelivery` 和队列消息之间的关联 ID 是跨进程恢复依据,不能只保存在内存。
- 最终回执以当前尝试和分片审计聚合;旧尝试不得覆盖新尝试的终态。
- 发送链拆分必须运行第 8 节中 SendChain、Billing、Gateway queue 和 Gateway protocol 四组门禁。
## 4. Gateway 入站 Server
| 职责组 | 当前入口/处理器 | 外部状态 | 不变量 |
|---|---|---|---|
| Bind 与鉴权 | CMPP 2.0/3.0 CONNECT、账号鉴权 | NestJS API、Redis presence | disabled 新提交与 receipt-draining 状态必须区分 |
| Submit | 报文归一化、长短信字段解析、调用 API、返回 SubmitResp | NestJS `/inbound/submit` | Sequence_Id 原样响应;API 结果与协议状态一致 |
| 会话与心跳 | ACTIVE_TEST、连接注册/移除 | Redis、API connection events | 心跳超时不保留伪在线连接 |
| 下游 Deliver | 选择会话、写报文、注册 ACK | 内存 ACK registry、API | CMPP 2.0/3.0 报文分别正确;非零 Msg_Id |
| ACK | DELIVER_RESP 匹配、成功/失败回调、超时 | ACK timer、API | 连接/Sequence_Id/Msg_Id 不得串线;超时只回调一次 |
| 恢复 | 账号在线状态与历史待投递恢复 | Redis recovery lock | 锁、退避和 stale owner 不得互相覆盖 |
| 协议日志 | 入站/出站报文安全日志 | API protocol log | 方向、命令、Sequence_Id 正确;不记录明文密码 |
## 5. Gateway 上游 Manager
| 职责组 | 当前入口/处理器 | 外部状态 | 不变量 |
|---|---|---|---|
| 连接池 | connect/disconnect、desired connections | 供应商 TCP、状态回调 | 连接数量与状态回调一致 |
| 重连 | supervisor、退避、鉴权失败分类 | timer、连接状态 | 网络退避封顶;鉴权失败慢速重试;人工停用不自动拉起 |
| Submit | 窗口、Sequence_Id、长短信分片 | CMPP TCP、tracker | 窗口不超限;每分片映射独立;结果可跨重启关联 |
| 回执 | DELIVER receipt 解析与映射 | API/Redis Stream | 通道、目标号码、Msg_Id 联合约束,歧义不误配 |
| 上行 | MO 解析与事件发布 | API/Redis Stream | 内容编码、源/目的号码和协议版本保持 |
| 心跳 | ACTIVE_TEST 和断线判定 | timer、连接池 | 心跳超时只触发一次连接丢失处理 |
## 6. 其余大服务
### ChannelsService
- 公开职责:通道/通道组 CRUD、组成员、路由规则、连接状态、通道测试、健康指标、报备字段、报备任务/记录、回执导入、删除治理。
- 主要表:`SmsChannel``SmsChannelGroup``SmsChannelGroupItem``ChannelRouteRule``CmppConnectionState``ChannelHealthMetric``ChannelReportField``ChannelSignatureReportTask/Record`
- 副作用:Gateway connect/disconnect、通道测试真实提交、报备文件导入导出。
- 禁区:连接控制与数据库状态不可只完成一侧;通道测试不得混入业务计费;删除前依赖检查必须保留。
### SmsConfigService
- 公开职责:应用、签名、模板、引流信息、通用资料字段、客户安全视图、下游连接事件与停用生命周期。
- 主要表:`SmsApplication``SmsSignature``SmsTemplate``SmsDrainageInfo``SignatureMaterial``SignatureReportMaterial``CmppDownstreamConnection/Delivery``AuditRecord`
- 副作用:审核/操作日志、Gateway 连接生命周期。
- 禁区:客户端响应必须继续使用专用安全选择字段;审核状态与通道报备状态不得混为一列。
### OperationsService
- 公开职责:短信/上行/任务分页与导出、运营看板、发送质量、签名通道质量、操作日志、死信、下游投递与恢复、分片审计、全链路追踪、对账。
- 主要表:短信、提交、回执、账务、连接、审计及企业配置相关读模型。
- 副作用:CSV 输出、下游恢复查询/操作;其余应保持只读。
- 禁区:分页总数必须来自数据库;上海时区边界不可依赖数据库会话时区;客户端查询不得泄露通道和内部路由。
### ReportMaterialsService
- 公开职责:官方模板、待生成资料分页/导出、导入配置、导入预览/提交、逐行/批量/整批审核、生成报备批次、批次导出和状态更新。
- 主要表:`ReportMaterialImportProfile/Batch/Item``ReportMaterialBatch/Item``ReportExportFile/Item`、签名/引流/通道报备表。
- 副作用:文件解析、导出文件、对象存储。
- 禁区:导入不得自动审核通过;逐行、勾选和整批审核使用同一状态机;批次生成必须幂等。
## 7. 前端门面与样式
### adminApi.ts
`adminApi` 继续作为稳定导出。其方法按以下域归档,R1 拆分时只能在内部委托,不批量修改页面 import:
- auth/users/roles/permissions
- tenants/applications/certification
- channels/channelGroups/routes/connections/tests
- signatures/templates/drainage/reportMaterials
- riskReview/blacklist/phoneFrequency
- operations/dashboard/messages/uplink/tracing
- reports/reconciliation/profit/quality
- billing/accounts/recharges
- files/audit/deletion governance
HTTP 基址、认证头、错误转换、下载和上传只能由 core 层统一实现;业务域文件不得各写一套。
### global.css
R3 前只允许新增带页面或组件命名空间的规则。拆分时按 token、基础组件、布局、页面域、响应式五层迁移;每批迁移后做桌面和窄屏截图对比。禁止一边迁移一边重新设计页面。
## 8. R0 固定特征测试矩阵
| 门禁 | 命令 | 覆盖 |
|---|---|---|
| 队列契约 | `node tools/spike/validate-gateway-queue-contract.mjs` | Redis Stream 四类消息 |
| R0 清单 | `node tools/quality/verify-refactor-r0.mjs` | 核心门面、契约样例、关键测试名称 |
| 发送链 | `npm --prefix api test -- --runInBand --forceExit send-chain.service.spec.ts` | 并发、幂等、路由、回执、下游 |
| 账务 | `npm --prefix api test -- --runInBand --forceExit billing.service.spec.ts` | 冻结、扣费、释放、退款、并发重放 |
| Gateway | `go test ./...``gateway` 目录) | CMPP、ACK、重连、队列和 tracker |
| Gateway 静态检查 | `go vet ./...``gateway` 目录) | Go 静态错误 |
| API 全量 | `npm --prefix api test -- --runInBand --forceExit` | NestJS 全量行为 |
| 构建 | `npm --prefix api run build``npm run build` | API/前端类型及生产产物 |
R0 本身不移动生产代码;后续版本若修改了上述不变量,必须先把它作为独立 Bug/需求处理,不得伪装为“纯拆分”。