## Context 当前君鸿CMP系统存在两个独立的模块: 1. **客户端实名跳转功能**(`internal/handler/app/client_realname.go`):提供实名链接获取接口 2. **轮询系统手动触发功能**(`internal/service/polling/manual_trigger_service.go`):支持手动触发卡状态检查 两个模块功能完整但相互独立,导致用户主动实名时无法享受优先级检查的好处。同时手动触发功能存在技术债务需要修复。 **现有架构**: ``` 客户端 → ClientRealnameHandler.GetRealnameLink() → 返回实名链接 (独立运行,无后续动作) 管理员 → PollingManualTriggerHandler → ManualTriggerService.TriggerSingle() (仅管理员可用,客户端无法触发) ``` ## Goals / Non-Goals **Goals:** - 在用户主动获取实名链接时自动触发该ICCID的实名检查优先级提升 - 修复手动触发功能的去重机制时间不对齐问题 - 优化手动触发的频次限制和权限检查逻辑 - 保持现有API接口的响应时间和兼容性 - 确保新功能的稳定性和可观测性 **Non-Goals:** - 不修改客户端实名跳转的核心流程和响应格式 - 不改变手动触发API的对外接口 - 不增加新的权限管理复杂性 - 不引入新的外部依赖或中间件 ## Decisions ### 决策1:异步触发设计 **选择**:使用 goroutine 异步调用手动触发服务 **理由**: - 避免影响实名链接API的响应时间(目标 < 5ms 影响) - 手动触发失败不应阻断主流程 - 用户无需等待触发结果,实名链接获取成功即可 **实现要点(强制)**: - goroutine 内部必须使用 `context.WithTimeout(context.Background(), 3*time.Second)` 创建独立 context - **禁止**在 goroutine 内复用 `c.UserContext()`:Fiber 请求 context 在 handler 返回后即失效,goroutine 中使用会导致操作失败或 context canceled 错误 **备选方案**: - 同步调用:会影响响应时间,用户体验下降 - 异步任务队列:过度设计,增加系统复杂性 ### 决策2:权限适配策略 **选择**:使用系统用户身份调用手动触发服务 **理由**: - 个人客户无管理员权限,无法直接调用手动触发 - 系统用户身份可绕过权限检查但保留操作记录 - 通过配置管理系统用户ID,便于维护 **备选方案**: - 修改权限检查:破坏现有权限模型 - 创建专用接口:增加代码重复 ### 决策3:去重机制修复 **选择**:去重key TTL调整为24小时,与日限制周期对齐 **理由**: - 解决当前1小时TTL与24小时限制不匹配的问题 - 确保同一卡在同一天内不会重复触发相同检查 - Redis内存消耗增加可控(估计 < 10MB) ### 决策4:频次限制优化 **选择**:将每日限制从100次调整为500次 **理由**: - 当前100次限制过低,客户端自动触发会快速消耗额度 - 500次既满足自动化需求,又能防止滥用 - 保留1000张卡的单次限制不变 ### 决策5:依赖注入方式 **选择**:在ClientRealnameHandler中新增ManualTriggerService字段 **理由**: - 遵循项目既有的结构体字段注入模式 - 在bootstrap/services.go中统一管理依赖 - 避免循环依赖问题 ## Risks / Trade-offs ### 风险1:异步调用失败无感知 **影响**:用户获取实名链接成功,但优先级触发失败,仍需等待定时轮询 **缓解措施**: - 增加详细的错误日志记录,便于运维监控 - 设置合理的超时时间,避免goroutine泄露 - 考虑增加Prometheus指标监控异步调用成功率 ### 风险2:Redis内存使用增加 **影响**:去重key TTL延长至24小时,Redis内存使用量增加 **缓解措施**: - 预估增加量:约10MB(假设每日1000次触发) - 定期清理过期key,确保Redis稳定运行 - 监控Redis内存使用情况 ### 风险3:频次限制调整可能被滥用 **影响**:500次限制仍可能被恶意用户快速消耗 **缓解措施**: - 保留现有的权限检查和日志记录 - 增加基于IP的限流保护 - 必要时可通过配置动态调整限制值 ### 风险4:系统用户身份权限过高 **影响**:系统用户可触发任意ICCID的检查,存在潜在安全风险 **缓解措施**: - 仅在客户端实名场景使用,且ICCID已通过归属权限验证 - 记录详细操作日志,包含原始客户ID - 系统用户ID通过配置管理,不硬编码 ## Migration Plan ### 阶段1:代码实现和测试 1. 修复手动触发服务的去重机制和频次限制 2. 在ClientRealnameHandler中集成异步调用 3. 更新依赖注入配置 4. 编写单元测试和集成测试 ### 阶段2:部署和监控 1. 在测试环境验证功能正确性 2. 配置生产环境的系统用户ID 3. 部署到生产环境 4. 监控异步调用成功率和系统性能 ### 回滚策略 - **代码回滚**:移除异步调用代码,恢复原有逻辑 - **配置回滚**:调整频次限制和去重TTL到原有值 - **数据清理**:清理测试期间产生的触发日志 ## Open Questions 1. **系统用户ID配置方式**:是否使用环境变量还是数据库配置? 2. **监控指标选择**:是否需要添加Prometheus指标监控? 3. **异步调用超时时间**:设置为多少秒比较合理?(建议3秒) 4. **是否需要熔断机制**:当手动触发服务频繁失败时是否需要暂停自动触发?