# 元数据容器与原子性部署需求 ## 元数据 - 需求编号:014-4 - 创建时间:2026-01-26 - 创建人:SSOT 架构师 - 状态:已完成 - 优先级:高 - 父需求:[REQ-014](../REQ-014.md) - 关联代码:`com.sforce.soap.tooling.MetadataContainer`, `com.sforce.soap.tooling.ContainerAsyncRequest`, `com.sforce.soap.tooling.DeployDetails` ## 需求概述 实现基于 Tooling API 的“事务原子性”代码部署模块。通过 `MetadataContainer` 机制,支持将多个 Apex 类、触发器、Visualforce 页面等成员的修改打包,一次性原子部署。此机制是 Salesforce IDE 开发的核心,确保代码依赖的一致性。 ## 目标 1. **原子性保证**:多文件修改(如 Class A 引用 Class B)必须作为一个事务提交,要么全成功,要么全失败。 2. **编译与测试**:在部署过程中自动触发编译检查,并可选执行测试用例。 3. **状态反馈**:提供详细的部署结果,包括每一行的编译错误或测试失败信息。 ## 功能需求 ### 1. 容器生命周期管理 (Container Lifecycle) 必须处理容器名称冲突问题(MetadataContainer Name 必须唯一)。 - `createContainer(String name)`: 创建新容器。如果同名容器已存在,应先尝试删除或使用唯一后缀生成新名称。 - `deleteContainer(String id)`: 部署完成后或发生异常时,清理容器以释放资源。 ### 2. 成员管理 (Member Management) 支持添加多种类型的元数据成员到容器中。 - `addMember(String containerId, String metadataType, String contentEntityId, String body)` - **metadataType**: 支持 `ApexClassMember`, `ApexTriggerMember`, `ApexComponentMember`, `ApexPageMember`。 - **contentEntityId**: 对应 `ApexClass` 或 `ApexTrigger` 的 ID。如果是新建文件,此字段可能为空(取决于 API 版本行为,通常 Tooling API 更新需 ID)。 - **body**: 新的代码内容。 ### 3. 异步部署请求 (Async Deployment) 创建 `ContainerAsyncRequest` 对象触发编译和部署。 - `deployContainer(String containerId, boolean isCheckOnly, boolean isRunTests)` - **IsCheckOnly**: `true` 仅编译验证(不保存);`false` 实际保存代码。 - **IsRunTests**: 是否在部署后运行测试(通常用于生产环境部署或验证)。 - 返回 `requestId` (ContainerAsyncRequest ID)。 ### 4. 状态轮询与结果解析 (Status Polling & Result Parsing) 由于部署是异步的,需要轮询状态并解析结果。 - `checkStatus(String requestId)` - 轮询 `ContainerAsyncRequest` 对象的 `State` 字段。 - **状态流转**: `Queued` -> `Processing` -> `Completed` / `Failed` / `Error` / `Invalidated` / `Aborted`。 - `getDeployDetails(String requestId)` - 当状态为 `Completed` 或 `Failed` 时,读取 `DeployDetails` 字段。 - **解析编译错误**: 遍历 `DeployDetails.getComponentFailures()` (对应 `DeployMessage` 数组),提取 `fileName`, `lineNumber`, `problem` 等信息。 - **解析测试结果**: 如果运行了测试,解析 `DeployDetails.getRunTestResult()`。 ## 数据结构与接口定义 ### 部署结果对象 (DeploymentResult) ```java public class DeploymentResult { private boolean success; private String status; // Completed, Failed, etc. private String errorMsg; // 系统级错误 private List compilationErrors; // 代码编译错误 } public class CompilationError { private String fileName; private int line; private int column; private String message; } ``` ## 异常处理 1. **容器名称冲突**: 捕获 `DUPLICATE_VALUE` 异常,自动重试或清理旧容器。 2. **成员添加失败**: 如 `contentEntityId` 无效或 `body` 为空,应在添加阶段报错。 3. **并发部署限制**: Salesforce 允许的并发 `ContainerAsyncRequest` 有限,需处理排队超时情况。 ## 技术约束 - **DeployDetails 引用**: 必须使用 `com.sforce.soap.tooling.DeployDetails` 类进行反序列化。 - **API 版本**: 确保使用的 Tooling API 版本支持当前的元数据类型。 - **CheckOnly 限制**: `CheckOnly=true` 不会修改服务器代码,但会生成编译结果,适用于“保存前语法检查”。 ## 成功标准 1. **原子性验证**: 创建一个依赖链(Class A 依赖修改后的 Class B),在同一个容器中部署成功。 2. **错误捕获**: 故意引入语法错误,部署状态应为 `Failed`,并能准确返回错误行号和错误信息。 3. **CheckOnly 模式**: 使用 `IsCheckOnly=true` 部署成功后,查询 `ApexClass` 内容确认未被修改。 ## 相关文档 - [设计文档](../design/2026-01-27-014-4-元数据容器与原子性部署-设计.md) - [决策记录](../decisions/adr/2026-01-27-014-4-ADR-元数据容器与原子性部署技术选型.md) - [提示词文档](../prompts/2026-01-27-014-4-prompt-元数据容器与原子性部署.md) - [变更日志](../changelog/2026-01-27-014-4-changelog.md) - [复盘文档](../retros/2026-01-27-014-4-retro.md) - [API 文档](../api-docs/2026-01-27-014-4-api.md)