- 阶段1:需求定义与入库 - 更新 index.md,标记 REQ-010-5 为阶段1-需求定义与入库 - 阶段2:方案决策 - 创建 ADR 文档:0014-metadata-api-client.md - 阶段3:提示词资产化 - 创建 Prompt 文档:005-metadata-api-client.md - 阶段4:执行会话与代码生成 - 创建会话记录:20260119-metadata-api-client.md - 阶段5:变更记录与归档 - 创建变更记录:20260119-metadata-api-client.md - 阶段6:闭环复盘 - 创建复盘报告:20260119-metadata-api-client-retro.md - 更新 index.md,标记 REQ-010-5 为已完成 - 更新 CHANGELOG.md,添加 Metadata API客户端封装的变更记录 所有文档均按照SSOT方法论创建,包括需求定义、架构决策、提示词资产化、执行会话、变更记录 和闭环复盘。
418 lines
14 KiB
Markdown
418 lines
14 KiB
Markdown
# 架构决策记录 - Metadata API客户端封装
|
||
|
||
## 背景
|
||
|
||
REQ-010-5 需要封装 Salesforce Metadata API 客户端,提供 retrieve() 和 deploy() 方法的调用接口,支持异步执行、状态轮询、Job ID 获取、Zip 文件下载、部署结果解析、错误处理机制等。
|
||
|
||
当前项目已经完成了数据库表结构设计、基础实体类和 Mapper 创建、Salesforce 组织配置管理、元数据任务定义管理等功能,现在需要实现 Metadata API 客户端封装,为后续的元数据拉取和部署功能提供基础。
|
||
|
||
## 决策
|
||
|
||
### 1. MetadataApiClient 客户端类创建方案
|
||
|
||
**决策**: 使用 Salesforce WSC (Web Service Connector) 库创建 MetadataApiClient 客户端类,封装 Salesforce Metadata API 调用。
|
||
|
||
**理由**:
|
||
- Salesforce WSC 库是官方推荐的 Java 客户端库,提供了完整的 Metadata API 支持
|
||
- WSC 库已经处理了 SOAP 协议的复杂性,简化了 API 调用
|
||
- WSC 库支持异步调用和状态轮询,满足业务需求
|
||
- WSC 库支持 OAuth 认证,与 SessionManager 集成方便
|
||
|
||
**实现方案**:
|
||
- 使用 Salesforce WSC 库创建 MetadataApiClient 客户端类
|
||
- 使用 SessionManager 进行会话管理和自动重新登录
|
||
- 使用 WSC 库的 MetadataConnection 类创建连接
|
||
- 使用 WSC 库的 RetrieveRequest 和 DeployRequest 类创建请求
|
||
- 使用 WSC 库的 AsyncResult 类处理异步结果
|
||
|
||
### 2. retrieve() 方法实现方案
|
||
|
||
**决策**: 使用异步线程池执行 retrieve() 方法,使用轮询机制检查任务状态,使用 ZipInputStream 处理 Zip 文件。
|
||
|
||
**理由**:
|
||
- 异步线程池可以避免阻塞主线程,提高系统响应速度
|
||
- 轮询机制可以及时获取任务状态,支持超时处理
|
||
- ZipInputStream 可以流式处理 Zip 文件,避免内存溢出
|
||
- 支持大文件处理,满足业务需求
|
||
|
||
**实现方案**:
|
||
- 使用 Spring 的 @Async 注解实现异步执行
|
||
- 使用 ThreadPoolTaskExecutor 配置线程池
|
||
- 使用 WSC 库的 checkStatus() 方法检查任务状态
|
||
- 使用 ScheduledExecutorService 实现轮询机制
|
||
- 使用 ZipInputStream 处理 Zip 文件,使用流式处理避免内存溢出
|
||
|
||
### 3. deploy() 方法实现方案
|
||
|
||
**决策**: 使用异步线程池执行 deploy() 方法,使用轮询机制检查任务状态,使用 JSON 解析库处理 API 响应。
|
||
|
||
**理由**:
|
||
- 异步线程池可以避免阻塞主线程,提高系统响应速度
|
||
- 轮询机制可以及时获取任务状态,支持超时处理
|
||
- JSON 解析库可以灵活处理 API 响应,提取错误信息和代码覆盖率
|
||
- 支持多种部署状态,满足业务需求
|
||
|
||
**实现方案**:
|
||
- 使用 Spring 的 @Async 注解实现异步执行
|
||
- 使用 ThreadPoolTaskExecutor 配置线程池
|
||
- 使用 WSC 库的 checkStatus() 方法检查任务状态
|
||
- 使用 ScheduledExecutorService 实现轮询机制
|
||
- 使用 Jackson 库处理 API 响应,使用正则表达式提取错误信息
|
||
|
||
### 4. 状态轮询机制方案
|
||
|
||
**决策**: 使用定时任务实现轮询机制,使用超时机制防止无限轮询,使用取消机制支持取消轮询。
|
||
|
||
**理由**:
|
||
- 定时任务可以定期检查任务状态,及时获取任务进度
|
||
- 超时机制可以防止无限轮询,避免资源浪费
|
||
- 取消机制可以支持用户取消任务,提高用户体验
|
||
- 轮询频率合理,避免 API 限流
|
||
|
||
**实现方案**:
|
||
- 使用 ScheduledExecutorService 实现定时任务
|
||
- 使用 Future 接口支持取消操作
|
||
- 使用 TimeoutException 处理超时情况
|
||
- 使用指数退避算法调整轮询频率,避免 API 限流
|
||
|
||
### 5. Zip 文件处理方案
|
||
|
||
**决策**: 使用 ZipInputStream 处理 Zip 文件,使用流式处理避免内存溢出,支持大文件处理。
|
||
|
||
**理由**:
|
||
- ZipInputStream 是 Java 标准库的一部分,无需引入额外依赖
|
||
- ZipInputStream 支持流式处理,可以逐个文件处理,避免内存溢出
|
||
- 支持大文件处理,满足业务需求
|
||
- 内存使用合理,不会因为文件过大导致内存溢出
|
||
|
||
**实现方案**:
|
||
- 使用 ZipInputStream 处理 Zip 文件
|
||
- 使用 BufferedInputStream 提高读取性能
|
||
- 使用 ByteArrayOutputStream 临时存储文件内容
|
||
- 使用 FileOutputStream 保存文件到磁盘
|
||
|
||
### 6. 部署结果解析方案
|
||
|
||
**决策**: 使用 Jackson 库处理 API 响应,使用正则表达式提取错误信息和代码覆盖率。
|
||
|
||
**理由**:
|
||
- Jackson 库是 Java 标准的 JSON 解析库,性能高,功能强大
|
||
- 正则表达式可以灵活提取错误信息和代码覆盖率
|
||
- 支持多种部署状态,满足业务需求
|
||
- 错误信息详细,方便用户排查问题
|
||
|
||
**实现方案**:
|
||
- 使用 Jackson 库的 ObjectMapper 类处理 API 响应
|
||
- 使用 JsonNode 类遍历 JSON 数据
|
||
- 使用 Pattern 和 Matcher 类提取错误信息和代码覆盖率
|
||
- 使用自定义异常类处理部署错误
|
||
|
||
### 7. 错误处理机制方案
|
||
|
||
**决策**: 使用统一的异常处理机制,使用重试机制处理网络异常,使用日志记录机制记录错误信息。
|
||
|
||
**理由**:
|
||
- 统一的异常处理机制可以简化代码,提高代码质量
|
||
- 重试机制可以处理网络异常,提高系统稳定性
|
||
- 日志记录机制可以记录错误信息,方便排查问题
|
||
- 支持多种异常类型,满足业务需求
|
||
|
||
**实现方案**:
|
||
- 使用自定义异常类封装 API 调用异常
|
||
- 使用 @Retryable 注解实现重试机制
|
||
- 使用 Slf4j 记录错误信息
|
||
- 使用 GlobalExceptionHandler 统一处理异常
|
||
|
||
## 备选方案
|
||
|
||
### 1. MetadataApiClient 客户端类创建备选方案
|
||
|
||
**备选方案 1**: 使用 Salesforce REST API 创建 MetadataApiClient 客户端类
|
||
|
||
**优点**:
|
||
- REST API 是轻量级的,易于使用
|
||
- 不需要引入额外的依赖
|
||
|
||
**缺点**:
|
||
- REST API 功能有限,不支持所有 Metadata API 功能
|
||
- 需要手动处理 SOAP 协议,开发成本高
|
||
- 不支持异步调用和状态轮询
|
||
|
||
**备选方案 2**: 使用第三方库创建 MetadataApiClient 客户端类
|
||
|
||
**优点**:
|
||
- 第三方库可能提供更友好的 API
|
||
- 可能提供额外的功能
|
||
|
||
**缺点**:
|
||
- 第三方库可能不稳定,维护成本高
|
||
- 第三方库可能不支持所有 Metadata API 功能
|
||
- 第三方库可能不兼容 WSC 库
|
||
|
||
### 2. retrieve() 方法实现备选方案
|
||
|
||
**备选方案 1**: 使用同步方式实现 retrieve() 方法
|
||
|
||
**优点**:
|
||
- 实现简单,不需要处理异步逻辑
|
||
- 代码易于理解和维护
|
||
|
||
**缺点**:
|
||
- 同步方式会阻塞主线程,影响系统响应速度
|
||
- 不支持超时处理和取消操作
|
||
|
||
**备选方案 2**: 使用消息队列实现 retrieve() 方法
|
||
|
||
**优点**:
|
||
- 消息队列可以解耦任务提交和任务执行
|
||
- 支持任务持久化和重试
|
||
|
||
**缺点**:
|
||
- 消息队列增加了系统复杂度
|
||
- 需要引入额外的依赖
|
||
|
||
### 3. deploy() 方法实现备选方案
|
||
|
||
**备选方案 1**: 使用同步方式实现 deploy() 方法
|
||
|
||
**优点**:
|
||
- 实现简单,不需要处理异步逻辑
|
||
- 代码易于理解和维护
|
||
|
||
**缺点**:
|
||
- 同步方式会阻塞主线程,影响系统响应速度
|
||
- 不支持超时处理和取消操作
|
||
|
||
**备选方案 2**: 使用消息队列实现 deploy() 方法
|
||
|
||
**优点**:
|
||
- 消息队列可以解耦任务提交和任务执行
|
||
- 支持任务持久化和重试
|
||
|
||
**缺点**:
|
||
- 消息队列增加了系统复杂度
|
||
- 需要引入额外的依赖
|
||
|
||
### 4. 状态轮询机制备选方案
|
||
|
||
**备选方案 1**: 使用回调机制实现状态轮询
|
||
|
||
**优点**:
|
||
- 回调机制可以及时获取任务状态
|
||
- 不需要定时任务,实现简单
|
||
|
||
**缺点**:
|
||
- Salesforce Metadata API 不支持回调机制
|
||
- 需要使用 Webhook,增加系统复杂度
|
||
|
||
**备选方案 2**: 使用 WebSocket 实现状态轮询
|
||
|
||
**优点**:
|
||
- WebSocket 可以实时推送任务状态
|
||
- 用户体验好
|
||
|
||
**缺点**:
|
||
- WebSocket 增加了系统复杂度
|
||
- 需要引入额外的依赖
|
||
|
||
### 5. Zip 文件处理备选方案
|
||
|
||
**备选方案 1**: 使用 ZipFile 类处理 Zip 文件
|
||
|
||
**优点**:
|
||
- ZipFile 类提供了随机访问功能
|
||
- 可以直接读取 Zip 文件中的文件
|
||
|
||
**缺点**:
|
||
- ZipFile 类需要将整个 Zip 文件加载到内存,可能导致内存溢出
|
||
- 不支持大文件处理
|
||
|
||
**备选方案 2**: 使用第三方库处理 Zip 文件
|
||
|
||
**优点**:
|
||
- 第三方库可能提供更好的性能
|
||
- 可能提供额外的功能
|
||
|
||
**缺点**:
|
||
- 第三方库增加了依赖
|
||
- 可能不稳定
|
||
|
||
### 6. 部署结果解析备选方案
|
||
|
||
**备选方案 1**: 使用 XML 解析库处理 API 响应
|
||
|
||
**优点**:
|
||
- XML 解析库可以处理 XML 格式的 API 响应
|
||
|
||
**缺点**:
|
||
- XML 解析库增加了依赖
|
||
- XML 解析比 JSON 解析慢
|
||
|
||
**备选方案 2**: 使用字符串处理提取错误信息和代码覆盖率
|
||
|
||
**优点**:
|
||
- 字符串处理不需要引入额外的依赖
|
||
- 实现简单
|
||
|
||
**缺点**:
|
||
- 字符串处理容易出错,维护成本高
|
||
- 不支持复杂的提取逻辑
|
||
|
||
### 7. 错误处理机制备选方案
|
||
|
||
**备选方案 1**: 使用 try-catch 处理异常
|
||
|
||
**优点**:
|
||
- try-catch 是 Java 标准的异常处理机制
|
||
- 实现简单
|
||
|
||
**缺点**:
|
||
- try-catch 需要在每个方法中重复编写,代码冗余
|
||
- 不支持重试机制
|
||
|
||
**备选方案 2**: 使用 AOP 实现异常处理
|
||
|
||
**优点**:
|
||
- AOP 可以统一处理异常,减少代码冗余
|
||
- 支持切面编程,灵活度高
|
||
|
||
**缺点**:
|
||
- AOP 增加了系统复杂度
|
||
- 需要引入额外的依赖
|
||
|
||
## 影响
|
||
|
||
### 系统架构影响
|
||
|
||
- 新增 MetadataApiClient 客户端类,封装 Salesforce Metadata API 调用
|
||
- 新增异步线程池,支持异步执行
|
||
- 新增状态轮询机制,支持任务状态查询
|
||
- 新增 Zip 文件处理功能,支持大文件处理
|
||
- 新增部署结果解析功能,支持错误信息和代码覆盖率提取
|
||
- 新增错误处理机制,支持异常处理和重试
|
||
|
||
### 开发流程影响
|
||
|
||
- 需要引入 Salesforce WSC 库依赖
|
||
- 需要配置异步线程池
|
||
- 需要编写单元测试和集成测试
|
||
- 需要编写使用文档
|
||
|
||
### 运维管理影响
|
||
|
||
- 需要监控异步线程池的使用情况
|
||
- 需要监控状态轮询的频率
|
||
- 需要监控 Zip 文件处理的性能
|
||
- 需要监控 API 调用的成功率
|
||
|
||
## 风险
|
||
|
||
### 技术风险
|
||
|
||
- **WSC 库版本兼容性风险**: WSC 库版本可能与项目其他依赖不兼容
|
||
- **异步执行风险**: 异步执行机制复杂可能导致状态管理困难
|
||
- **状态轮询风险**: 状态轮询频率不当可能导致 API 限流
|
||
- **Zip 文件处理风险**: Zip 文件处理不当可能导致内存溢出
|
||
- **错误处理风险**: 错误处理不完善可能导致任务失败无法恢复
|
||
|
||
### 业务风险
|
||
|
||
- **API 调用失败风险**: API 调用失败可能导致元数据拉取和部署失败
|
||
- **任务状态不一致风险**: 任务状态不一致可能导致用户困惑
|
||
- **数据丢失风险**: Zip 文件处理失败可能导致数据丢失
|
||
- **部署失败风险**: 部署失败可能导致系统不可用
|
||
|
||
### 实施风险
|
||
|
||
- **开发时间风险**: 开发时间可能超出预期
|
||
- **测试时间风险**: 测试时间可能超出预期
|
||
- **上线时间风险**: 上线时间可能超出预期
|
||
|
||
## 回滚策略
|
||
|
||
如果决策实施后出现问题,可以采取以下回滚策略:
|
||
|
||
1. **回滚 WSC 库版本**: 如果 WSC 库版本兼容性问题,可以回滚到之前的版本
|
||
2. **禁用异步执行**: 如果异步执行机制有问题,可以禁用异步执行,使用同步方式
|
||
3. **调整轮询频率**: 如果状态轮询频率有问题,可以调整轮询频率
|
||
4. **禁用 Zip 文件处理**: 如果 Zip 文件处理有问题,可以禁用 Zip 文件处理,使用其他方式
|
||
5. **简化错误处理**: 如果错误处理机制有问题,可以简化错误处理,使用 try-catch
|
||
|
||
## 验收标准
|
||
|
||
定义验证该决策有效性的具体标准和测试方法:
|
||
|
||
1. **MetadataApiClient 客户端类创建验收标准**:
|
||
- MetadataApiClient 创建成功
|
||
- 使用 Salesforce WSC 库成功
|
||
- 与 SessionManager 集成成功
|
||
- 代码符合项目编码规范
|
||
|
||
2. **retrieve() 方法实现验收标准**:
|
||
- retrieve() 方法调用成功
|
||
- 支持异步执行
|
||
- 支持 Job ID 获取
|
||
- 支持状态轮询
|
||
- 支持 Zip 文件下载
|
||
- 错误处理机制正常工作
|
||
|
||
3. **deploy() 方法实现验收标准**:
|
||
- deploy() 方法调用成功
|
||
- 支持异步执行
|
||
- 支持 Job ID 获取
|
||
- 支持状态轮询
|
||
- 支持部署结果解析
|
||
- 错误处理机制正常工作
|
||
|
||
4. **状态轮询机制验收标准**:
|
||
- 状态轮询机制正常工作
|
||
- 轮询频率合理
|
||
- 支持超时处理
|
||
- 支持取消轮询
|
||
|
||
5. **Zip 文件处理验收标准**:
|
||
- Zip 文件下载成功
|
||
- Zip 文件解压成功
|
||
- 支持大文件处理
|
||
- 内存使用合理
|
||
|
||
6. **部署结果解析验收标准**:
|
||
- 部署结果解析成功
|
||
- 错误信息提取正确
|
||
- 代码覆盖率提取正确
|
||
- 支持多种部署状态
|
||
|
||
7. **错误处理机制验收标准**:
|
||
- 错误处理机制正常工作
|
||
- 支持多种异常类型
|
||
- 错误信息详细
|
||
- 支持错误重试
|
||
|
||
## 视觉锚点
|
||
|
||
### Visual Reference
|
||
|
||
引用 Canvas 的具体节点或快照:
|
||
- [Authentication.canvas](../../Authentication.canvas) - 项目架构视觉化展示
|
||
- **相关节点**: [集成核心](node_integration_core) - 提供与Salesforce的各种连接方式
|
||
- **相关节点**: [SessionManager](node_session_manager_detail) - 会话管理,提供登录服务
|
||
|
||
### Status
|
||
|
||
- [x] Draft
|
||
- [ ] Accepted
|
||
- [ ] Superceded
|
||
|
||
## 参考资料
|
||
|
||
列出与该决策相关的参考资料,包括文档、文章或其他资源:
|
||
|
||
- [REQ-010-5.md](../requirements/REQ-010-5.md) - Metadata API客户端封装需求文档
|
||
- [REQ-010-1.md](../requirements/REQ-010-1.md) - 数据库表结构设计和创建
|
||
- [REQ-010-2.md](../requirements/REQ-010-2.md) - 基础实体类和Mapper创建
|
||
- [REQ-010-3.md](../requirements/REQ-010-3.md) - Salesforce组织配置管理
|
||
- [REQ-010-4.md](../requirements/REQ-010-4.md) - 元数据任务定义管理
|
||
- [Salesforce Metadata API Developer Guide](https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/) - Salesforce Metadata API 官方文档
|
||
- [Salesforce WSC (Web Service Connector)](https://github.com/forcedotcom/wsc) - Salesforce WSC 库 GitHub 仓库
|
||
- [Spring Async Documentation](https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#scheduling-annotation-support-async) - Spring 异步支持文档
|