# 架构决策记录 - 元数据部署核心功能 ## 背景 在 REQ-010-6(元数据拉取核心功能)和 REQ-010-7(文件存储和解压处理)中,我们已经实现了从 Salesforce Metadata API 拉取元数据的功能,以及文件存储和解压处理功能。现在需要实现元数据部署的核心功能,将本地的元数据部署到 Salesforce 组织中。 本需求面临的主要问题包括: 1. 部署操作可能需要较长时间,需要异步执行避免阻塞主线程 2. 需要实时监控部署状态,及时反馈部署进度 3. 需要支持部署取消功能,避免长时间运行的部署任务占用资源 4. 需要记录部署历史,便于查询和审计 5. 需要解析部署结果,提取错误信息和代码覆盖率 相关约束条件: - 必须基于现有的 Spring Boot 3 + Vue 3 技术栈 - 必须在 datai-salesforce-metadata 模块下实现 - 必须使用 SessionManager 进行会话管理和自动重新登录 - 必须使用现有的集成核心功能进行 Salesforce API 调用 - 必须使用异步线程池执行长时间任务 - 必须遵循现有的异常处理机制和日志记录规范 ## 决策 ### 1. 手动触发部署方案 **决策**: 使用 RESTful API 接口实现手动触发部署,调用 MetadataApiClient 的 deploy() 方法。 **理由**: - RESTful API 是标准的接口设计模式,易于使用和理解 - 可以与前端组件无缝集成 - 支持多种客户端(Web、移动端、第三方应用) - 符合项目现有的 API 设计规范 **实现方案**: - 创建 MetadataDeployController 控制器 - 提供 POST /metadata/deploy/trigger 接口 - 接收任务ID、组织配置ID和Zip文件作为参数 - 调用 MetadataApiService 的 deployAsync() 方法 - 返回 Job ID 和初始状态 ### 2. 异步部署执行方案 **决策**: 使用 Spring 的 @Async 注解和自定义线程池实现异步部署执行。 **理由**: - Spring 的 @Async 注解简化了异步编程 - 自定义线程池可以更好地控制并发度和资源使用 - 支持并发部署,提高系统吞吐量 - 部署任务不阻塞系统响应,提高用户体验 **实现方案**: - 配置自定义线程池(ThreadPoolTaskExecutor) - 使用 @Async 注解标记异步方法 - 异步方法中调用 MetadataApiClient 的 deploy() 方法 - 使用 Future 对象跟踪异步任务状态 ### 3. 状态监控方案 **决策**: 使用状态机模式管理部署状态,使用轮询机制检查部署状态。 **理由**: - 状态机模式可以清晰地定义状态转换规则 - 轮询机制简单可靠,易于实现 - 可以实时监控部署状态,及时反馈部署进度 - 支持多种部署状态(Pending/Processing/Success/Failed/Partial_Success/Cancelled) **实现方案**: - 定义 DeployStatus 枚举(Pending/Processing/Success/Failed/Partial_Success/Cancelled) - 使用状态机管理部署状态转换 - 使用定时任务轮询部署状态 - 将状态更新到数据库(datai_meta_job_execution 表) ### 4. 部署历史记录方案 **决策**: 使用 MyBatis Plus 的 BaseMapper 实现部署历史记录查询。 **理由**: - MyBatis Plus 提供了强大的 CRUD 操作,简化开发 - 支持分页查询,提高查询性能 - 支持条件查询,灵活满足不同查询需求 - 符合项目现有的持久层框架 **实现方案**: - 使用 datai_meta_job_execution 表存储部署历史记录 - 使用 MyBatis Plus 的 BaseMapper 实现查询 - 支持分页查询(使用 Page 对象) - 支持条件查询(使用 QueryWrapper) ### 5. 部署进度查询方案 **决策**: 使用轮询机制获取部署进度,使用缓存提高查询性能。 **理由**: - 轮询机制简单可靠,易于实现 - 缓存可以提高查询性能,减少数据库访问 - 支持实时进度查询,提高用户体验 - 支持进度百分比显示,直观展示部署进度 **实现方案**: - 使用定时任务轮询部署状态 - 使用 ConcurrentHashMap 缓存部署进度信息 - 提供 GET /metadata/deploy/progress/{jobId} 接口查询进度 - 进度信息包括:状态、进度百分比、已处理组件数、总组件数 ### 6. 部署取消方案 **决策**: 使用 Future.cancel() 取消异步任务,使用状态机管理取消状态。 **理由**: - Future.cancel() 可以安全地取消异步任务 - 状态机可以清晰地管理取消状态 - 取消后资源正确释放,避免资源泄漏 - 取消状态更新及时,用户可以及时获知取消结果 **实现方案**: - 使用 Future.cancel() 取消异步任务 - 将状态更新为 Cancelled - 释放相关资源(如文件句柄、数据库连接等) - 记录取消日志,便于审计 ### 7. 部署结果解析方案 **决策**: 使用 JSON 解析库处理 API 响应,使用正则表达式提取错误信息。 **理由**: - JSON 解析库(如 Jackson)功能强大,易于使用 - 正则表达式可以灵活地提取错误信息 - 支持多种部署状态,适应不同场景 - 错误信息详细,便于问题排查 **实现方案**: - 使用 Jackson 解析 API 响应 - 提取部署状态、错误信息、代码覆盖率 - 使用正则表达式提取错误信息 - 将解析结果存储到数据库(datai_meta_job_log 表) ## 备选方案 ### 1. 手动触发部署方案备选 **备选方案 A**: 使用消息队列(如 RabbitMQ)触发部署。 **优点**: - 支持分布式部署 - 支持任务重试和死信队列 - 支持任务优先级 **缺点**: - 引入额外依赖,增加系统复杂度 - 部署成本高 - 对于简单的部署场景,过于重量级 **备选方案 B**: 使用定时任务触发部署。 **优点**: - 实现简单 **缺点**: - 不支持实时触发 - 用户体验差 - 不符合需求 ### 2. 异步部署执行方案备选 **备选方案 A**: 使用 CompletableFuture 实现异步执行。 **优点**: - Java 8 原生支持 - 支持链式调用和组合 **缺点**: - 不如 Spring 的 @Async 注解简洁 - 需要手动管理线程池 **备选方案 B**: 使用消息队列实现异步执行。 **优点**: - 支持分布式部署 - 支持任务重试和死信队列 **缺点**: - 引入额外依赖,增加系统复杂度 - 部署成本高 - 对于简单的异步场景,过于重量级 ### 3. 状态监控方案备选 **备选方案 A**: 使用事件驱动架构监控状态。 **优点**: - 实时性好 - 解耦度高 **缺点**: - 实现复杂 - 引入额外依赖(如消息队列) - 对于简单的状态监控,过于重量级 **备选方案 B**: 使用 WebSocket 推送状态更新。 **优点**: - 实时性好 - 用户体验好 **缺点**: - 实现复杂 - 需要维护长连接 - 对于简单的状态监控,过于重量级 ### 4. 部署历史记录方案备选 **备选方案 A**: 使用 Elasticsearch 存储部署历史记录。 **优点**: - 查询性能好 - 支持全文搜索 **缺点**: - 引入额外依赖,增加系统复杂度 - 部署成本高 - 对于简单的历史记录查询,过于重量级 **备选方案 B**: 使用 Redis 缓存部署历史记录。 **优点**: - 查询性能好 **缺点**: - 数据持久性差 - 不支持复杂查询 - 不符合需求 ### 5. 部署进度查询方案备选 **备选方案 A**: 使用 WebSocket 推送进度更新。 **优点**: - 实时性好 - 用户体验好 **缺点**: - 实现复杂 - 需要维护长连接 - 对于简单的进度查询,过于重量级 **备选方案 B**: 使用 Server-Sent Events (SSE) 推送进度更新。 **优点**: - 实时性好 - 实现相对简单 **缺点**: - 不支持双向通信 - 浏览器兼容性问题 - 对于简单的进度查询,过于重量级 ### 6. 部署取消方案备选 **备选方案 A**: 使用中断线程的方式取消部署。 **优点**: - 实现简单 **缺点**: - 不安全,可能导致资源泄漏 - 不推荐使用 - 不符合最佳实践 **备选方案 B**: 使用标志位的方式取消部署。 **优点**: - 实现简单 - 相对安全 **缺点**: - 需要在代码中频繁检查标志位 - 不如 Future.cancel() 简洁 ### 7. 部署结果解析方案备选 **备选方案 A**: 使用 XML 解析库处理 API 响应。 **优点**: - 功能强大 **缺点**: - API 响应主要是 JSON 格式 - 不如 JSON 解析库简洁 - 不符合需求 **备选方案 B**: 使用字符串操作提取错误信息。 **优点**: - 实现简单 **缺点**: - 不够灵活 - 容易出错 - 不如正则表达式强大 ## 影响 ### 系统架构影响 1. **新增模块**: 在 `datai-salesforce-metadata` 模块下新增 `deploy` 包,包含部署相关的服务、控制器、枚举和 DTO 2. **接口定义**: 定义 `IMetadataDeployService` 接口,提供统一的部署服务抽象 3. **状态机**: 使用状态机模式管理部署状态,提高状态管理的可维护性 4. **异步执行**: 使用 Spring 的 @Async 注解和自定义线程池实现异步部署执行 5. **轮询机制**: 使用定时任务轮询部署状态,实现实时监控 ### 开发流程影响 1. **开发工作量**: 需要开发 7 个主要功能模块,预计工作量 5-7 人天 2. **测试工作量**: 需要进行单元测试、集成测试和性能测试,预计工作量 3-4 人天 3. **代码规范**: 需要遵循项目现有的代码规范和设计模式 4. **文档维护**: 需要更新接口文档和 API 文档 ### 运维管理影响 1. **配置管理**: 需要新增配置项(线程池配置、轮询间隔等) 2. **监控告警**: 需要配置部署任务监控和告警通知 3. **日志管理**: 需要记录部署操作日志和错误日志 4. **任务管理**: 需要定期检查部署任务状态,清理过期任务 ## 风险 ### 技术风险 1. **异步执行风险**: 异步执行机制复杂可能导致状态管理困难 - **缓解措施**: 使用状态机模式管理状态,使用 Future 对象跟踪异步任务 - **监控指标**: 监控异步任务执行时间和状态转换 2. **状态轮询风险**: 状态轮询频率不当可能导致 API 限流 - **缓解措施**: 设置合理的轮询间隔(如 5 秒),使用指数退避策略 - **监控指标**: 监控 API 调用次数和响应时间 3. **部署取消风险**: 部署取消功能复杂可能导致资源泄漏 - **缓解措施**: 使用 Future.cancel() 安全取消,确保资源正确释放 - **监控指标**: 监控取消操作的成功率和资源释放情况 ### 业务风险 1. **历史记录风险**: 部署历史记录过多可能影响查询性能 - **缓解措施**: 使用分页查询,定期清理过期历史记录 - **监控指标**: 监控历史记录查询性能 2. **进度查询风险**: 进度查询不准确可能导致用户体验差 - **缓解措施**: 使用缓存提高查询性能,优化轮询策略 - **监控指标**: 监控进度查询的准确性和响应时间 3. **结果解析风险**: 部署结果解析不完善可能导致错误信息不准确 - **缓解措施**: 使用 JSON 解析库和正则表达式双重验证,充分测试 - **监控指标**: 监控结果解析的成功率和准确性 ### 实施风险 1. **性能风险**: 部署操作可能影响系统性能 - **缓解措施**: 使用异步执行,限制并发数,使用线程池管理资源 - **监控指标**: 监控系统 CPU 和内存使用情况 2. **兼容性风险**: 不同版本的 Salesforce Metadata API 可能存在兼容性问题 - **缓解措施**: 使用版本化的 API 客户端,充分测试 - **监控指标**: 监控 API 调用成功率和错误率 ## 回滚策略 ### 1. 手动触发部署回滚策略 如果手动触发部署出现问题,可以立即停止部署: 1. 禁用部署接口 2. 回滚已部署的元数据(如果有) 3. 修复问题后重新启用 ### 2. 异步部署执行回滚策略 如果异步部署执行出现问题,可以临时使用同步执行: 1. 修改代码,移除 @Async 注解 2. 限制并发数,避免系统过载 3. 优化后重新切换回异步执行 ### 3. 状态监控回滚策略 如果状态监控出现问题,可以临时使用数据库查询: 1. 修改代码,直接查询数据库获取状态 2. 优化后重新切换回轮询机制 ### 4. 整体回滚策略 如果整个功能出现问题,可以回滚到 REQ-010-7 的状态: 1. 停止使用元数据部署功能 2. 修复问题后重新启用 ## 验收标准 ### 功能验收标准 1. **手动触发部署** - [ ] 能够成功手动触发部署 - [ ] 支持选择任务ID - [ ] 支持选择组织配置 - [ ] 支持上传Zip文件 - [ ] 触发成功返回Job ID - [ ] API接口符合RESTful规范 2. **异步部署执行** - [ ] 异步部署执行正常工作 - [ ] 使用线程池管理异步任务 - [ ] 支持并发部署 - [ ] 部署任务不阻塞系统响应 3. **状态监控** - [ ] 状态监控正常工作 - [ ] 使用状态机管理部署状态 - [ ] 支持状态查询 - [ ] 状态更新及时 4. **部署历史记录** - [ ] 部署历史记录成功 - [ ] 支持分页查询 - [ ] 支持条件查询 - [ ] 历史记录完整 5. **部署进度查询** - [ ] 部署进度查询成功 - [ ] 支持实时进度查询 - [ ] 进度信息准确 - [ ] 支持进度百分比显示 6. **部署取消** - [ ] 部署取消功能正常工作 - [ ] 支持取消正在进行的部署任务 - [ ] 取消后资源正确释放 - [ ] 取消状态更新及时 7. **部署结果解析** - [ ] 部署结果解析成功 - [ ] 错误信息提取正确 - [ ] 代码覆盖率提取正确 - [ ] 支持多种部署状态 - [ ] 错误信息详细 ### 性能验收标准 1. **部署触发性能** - [ ] 部署触发响应时间 < 1s - [ ] 并发触发 10 个部署任务无性能下降 2. **状态轮询性能** - [ ] 状态轮询任务执行时间 < 1s - [ ] 不影响系统正常运行 3. **进度查询性能** - [ ] 进度查询响应时间 < 500ms - [ ] 并发查询 100 次无性能下降 4. **历史记录查询性能** - [ ] 历史记录查询响应时间 < 1s - [ ] 分页查询 100 条记录无性能下降 ### 安全性验收标准 1. **认证安全** - [ ] 部署操作需要认证 - [ ] 使用 SessionManager 进行会话管理 - [ ] 自动重新登录功能正常 2. **数据安全** - [ ] 部署数据传输加密 - [ ] 敏感信息不记录到日志 - [ ] 部署历史记录权限控制 ### 代码质量验收标准 1. **代码规范** - [ ] 代码符合项目编码规范 - [ ] 有清晰的注释 - [ ] 通过代码审查 2. **测试覆盖** - [ ] 单元测试覆盖率 > 80% - [ ] 集成测试覆盖主要场景 - [ ] 性能测试通过 3. **文档完整** - [ ] 接口文档完整 - [ ] API 文档完整 - [ ] 使用文档完整 ## 视觉锚点 ### Visual Reference 引用 Canvas 的具体节点或快照: - [Authentication.canvas](../../Authentication.canvas) - 项目架构视觉化展示 - **具体节点**: [集成核心](node_integration_core) - 提供与Salesforce的各种连接方式 - **具体节点**: [SessionManager](node_session_manager_detail) - 会话管理,提供登录服务 ### Status - [x] Draft - [ ] Accepted - [ ] Superceded ## 参考资料 列出与该决策相关的参考资料,包括文档、文章或其他资源: 1. [REQ-010-8.md](../requirements/REQ-010-8.md) - 元数据部署核心功能需求文档 2. [REQ-010-6.md](../requirements/REQ-010-6.md) - 元数据拉取核心功能需求文档 3. [REQ-010-7.md](../requirements/REQ-010-7.md) - 文件存储和解压处理需求文档 4. [004-元数据部署网页资料链接地址](../reference-code/metadata/004-元数据部署网页资料链接地址) - 官方文档和开源项目参考 5. [metadata-module.md](../reference-code/com/docs/metadata-module.md) - Salesforce Metadata API 模块说明 6. [index.md](../reference-code/com/docs/index.md) - Salesforce SOAP API Java 客户端参考文档