datai/docs/archive/decisions/adr/0014-metadata-api-client.md

418 lines
14 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.

# 架构决策记录 - 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 异步支持文档