# API 文档:003-03 部署操作 ## 元数据 - **需求编号**: 003-03 - **需求名称**: 部署操作 - **创建时间**: 2026-02-06 - **创建人**: AI Assistant - **版本号**: v1.0.0 - **状态**: 已完成 --- ## API 概述 部署操作 API 提供通用的 ZIP 部署服务,支持字节数组格式的 ZIP 文件部署、同步轮询、状态查询和取消部署功能。该服务与 003-02 的元数据类型定义功能完全解耦,通过通用字节流接口接收 ZIP 数据。 ### 核心功能 1. **部署 ZIP 包**: 接收 ZIP 文件进行元数据部署 2. **同步轮询**: 后端轮询直到部署完成(成功或失败) 3. **状态查询**: 通过 deployId 查询部署状态 4. **取消部署**: 取消正在进行的部署操作 ### 技术特点 - **通用字节流接口**: Service 层接收 `byte[]` 格式的 ZIP 数据 - **文件上传支持**: 支持最大 50MB 的 ZIP 文件上传 - **同步轮询机制**: 最多轮询 60 次,每 5 秒检查一次状态 - **异步日志记录**: 使用 Spring @Async 异步记录部署历史 - **完整错误码体系**: 定义 6 个标准错误码 --- ## 接口列表 ### 1. 部署 ZIP 包 **功能描述**: 接收 ZIP 文件进行元数据部署,返回部署 ID。 **请求方式**: POST **请求路径**: `/salesforce/metadata/deploy` **权限要求**: `salesforce:metadata:deploy` #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | file | MultipartFile | 是 | ZIP 文件,最大 50MB | | deployOptionsJson | String | 否 | 部署选项 JSON 字符串 | #### DeployOptions 字段说明 | 字段名 | 类型 | 默认值 | 说明 | |--------|------|--------|------| | allowMissingFiles | boolean | false | 是否允许缺少文件 | | autoUpdatePackage | boolean | false | 是否自动更新包 | | checkOnly | boolean | false | 是否只检查不部署 | | ignoreWarnings | boolean | false | 是否忽略警告 | | performRetrieve | boolean | false | 是否执行检索 | | purgeOnDelete | boolean | false | 删除时是否清除 | | rollbackOnError | boolean | true | 出错时是否回滚 | | testLevel | String | null | 测试级别(NoTestRun, RunSpecifiedTests, RunLocalTests, RunAllTestsInOrg) | | runTests | String[] | null | 指定要运行的测试类 | | singlePackage | boolean | true | 是否为单个包 | | validateOnly | boolean | false | 是否仅验证 | #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | int | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 部署结果 | #### data 字段说明 | 字段名 | 类型 | 说明 | |--------|------|------| | deployId | String | 部署 ID | #### 成功示例 ```json { "code": 200, "msg": "操作成功", "data": { "deployId": "0Afxx0000004M5sCAE" } } ``` #### 失败示例 ```json { "code": 500, "msg": "部署失败: 文件格式错误,请上传 ZIP 文件" } ``` #### 错误码 - 500: 部署失败 - 500: 文件格式错误(非 ZIP 文件) - 500: 文件大小超过 50MB 限制 --- ### 2. 检查部署状态 **功能描述**: 通过 deployId 查询当前部署状态。 **请求方式**: GET **请求路径**: `/salesforce/metadata/deploy/status/{deployId}` **权限要求**: `salesforce:metadata:deploy:query` #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | deployId | String | 是 | 部署 ID(路径参数) | #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | int | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 部署状态结果 | #### data 字段说明(DeployResultVo) | 字段名 | 类型 | 说明 | |--------|------|------| | success | boolean | 是否成功 | | id | String | 部署 ID | | status | String | 部署状态(Queued, InProgress, Succeeded, Failed, Canceled) | | numberComponentErrors | int | 组件错误数 | | numberComponentsDeployed | int | 已部署组件数 | | numberComponentsTotal | int | 总组件数 | | numberTestErrors | int | 测试错误数 | | numberTestsCompleted | int | 已完成测试数 | | numberTestsTotal | int | 总测试数 | | errorMessage | String | 错误消息 | | messages | List | 部署消息列表 | #### DeployMessageVo 字段说明 | 字段名 | 类型 | 说明 | |--------|------|------| | changed | boolean | 是否已更改 | | columnNumber | int | 列号 | | componentType | String | 组件类型 | | fileName | String | 文件名 | | fullName | String | 完整名称 | | lineNumber | int | 行号 | | problem | String | 问题描述 | | success | boolean | 是否成功 | #### 成功示例 ```json { "code": 200, "msg": "操作成功", "data": { "success": true, "id": "0Afxx0000004M5sCAE", "status": "Succeeded", "numberComponentErrors": 0, "numberComponentsDeployed": 5, "numberComponentsTotal": 5, "numberTestErrors": 0, "numberTestsCompleted": 10, "numberTestsTotal": 10, "errorMessage": null, "messages": [ { "changed": true, "columnNumber": 0, "componentType": "CustomObject", "fileName": "objects/Account.object", "fullName": "Account", "lineNumber": 0, "problem": null, "success": true } ] } } ``` #### 失败示例 ```json { "code": 500, "msg": "状态查询失败: 部署 ID 不存在" } ``` #### 错误码 - 500: 状态查询失败 --- ### 3. 同步轮询部署状态 **功能描述**: 后端轮询直到部署完成(成功或失败),最多轮询 60 次,每 5 秒一次,5 分钟超时。 **请求方式**: GET **请求路径**: `/salesforce/metadata/deploy/poll/{deployId}` **权限要求**: `salesforce:metadata:deploy:query` #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | deployId | String | 是 | 部署 ID(路径参数) | #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | int | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 部署结果(DeployResultVo) | #### data 字段说明 同"检查部署状态"接口的 data 字段。 #### 成功示例 ```json { "code": 200, "msg": "操作成功", "data": { "success": true, "id": "0Afxx0000004M5sCAE", "status": "Succeeded", "numberComponentErrors": 0, "numberComponentsDeployed": 5, "numberComponentsTotal": 5, "numberTestErrors": 0, "numberTestsCompleted": 10, "numberTestsTotal": 10, "errorMessage": null, "messages": [] } } ``` #### 失败示例 ```json { "code": 500, "msg": "部署超时(超过5分钟)" } ``` #### 错误码 - 500: 轮询被中断 - 500: 部署超时(超过5分钟) --- ### 4. 取消部署 **功能描述**: 取消正在进行的部署操作。 **请求方式**: POST **请求路径**: `/salesforce/metadata/deploy/cancel/{deployId}` **权限要求**: `salesforce:metadata:deploy:cancel` #### 请求参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | deployId | String | 是 | 部署 ID(路径参数) | #### 响应参数 | 参数名 | 类型 | 说明 | |--------|------|------| | code | int | 状态码(200 成功,其他失败) | | msg | String | 提示信息 | | data | Object | 取消结果 | #### data 字段说明 | 字段名 | 类型 | 说明 | |--------|------|------| | success | boolean | 是否成功取消 | #### 成功示例 ```json { "code": 200, "msg": "操作成功", "data": { "success": true } } ``` #### 失败示例 ```json { "code": 500, "msg": "取消部署失败: 部署已完成或已取消" } ``` #### 错误码 - 500: 取消部署失败 --- ## 错误码 ### 业务错误码 | 错误码 | 错误信息 | 说明 | 处理建议 | |--------|----------|------|----------| | METADATA_DEPLOY_001 | 部署失败 | 部署过程中发生错误 | 检查 ZIP 文件内容和部署选项 | | METADATA_DEPLOY_002 | 状态查询失败 | 查询部署状态时发生错误 | 检查 deployId 是否正确 | | METADATA_DEPLOY_003 | 轮询被中断 | 同步轮询过程中被中断 | 检查线程状态,重新发起轮询 | | METADATA_DEPLOY_004 | 取消部署失败 | 取消部署时发生错误 | 检查部署状态是否可取消 | | METADATA_DEPLOY_005 | 部署超时(超过5分钟) | 同步轮询超过 5 分钟 | 检查 Salesforce 服务状态,稍后重试 | | METADATA_DEPLOY_006 | 文件格式错误(非ZIP文件) | 上传的文件不是 ZIP 格式 | 请上传 ZIP 格式的文件 | ### HTTP 状态码 | 状态码 | 说明 | 处理建议 | |--------|------|----------| | 200 | 请求成功 | - | | 401 | 未授权 | 检查用户权限 | | 403 | 禁止访问 | 检查用户角色权限 | | 404 | 资源不存在 | 检查请求路径和参数 | | 500 | 服务器内部错误 | 查看错误日志,联系管理员 | --- ## 部署状态说明 | 状态 | 说明 | 是否终态 | |------|------|----------| | Queued | 已排队,等待执行 | 否 | | InProgress | 正在进行中 | 否 | | Succeeded | 部署成功 | 是 | | Failed | 部署失败 | 是 | | Canceled | 已取消 | 是 | --- ## 使用示例 ### 场景 1:部署 ZIP 包并轮询结果 ```java // 1. 部署 ZIP 包 MultipartFile zipFile = ...; // 获取 ZIP 文件 String deployOptionsJson = "{\"rollbackOnError\":true,\"testLevel\":\"RunLocalTests\"}"; AjaxResult result = deployController.deploy(zipFile, deployOptionsJson); String deployId = (String) ((Map) result.get("data")).get("deployId"); // 2. 同步轮询直到部署完成 AjaxResult pollResult = deployController.pollStatus(deployId); DeployResultVo deployResult = (DeployResultVo) pollResult.get("data"); // 3. 处理结果 if (deployResult.isSuccess()) { System.out.println("部署成功!"); } else { System.out.println("部署失败:" + deployResult.getErrorMessage()); } ``` ### 场景 2:查询部署状态 ```java // 查询部署状态 String deployId = "0Afxx0000004M5sCAE"; AjaxResult result = deployController.checkStatus(deployId); DeployResultVo deployResult = (DeployResultVo) result.get("data"); System.out.println("部署状态:" + deployResult.getStatus()); System.out.println("已部署组件数:" + deployResult.getNumberComponentsDeployed()); System.out.println("总组件数:" + deployResult.getNumberComponentsTotal()); ``` ### 场景 3:取消部署 ```java // 取消部署 String deployId = "0Afxx0000004M5sCAE"; AjaxResult result = deployController.cancelDeploy(deployId); boolean success = (Boolean) ((Map) result.get("data")).get("success"); if (success) { System.out.println("取消部署成功!"); } else { System.out.println("取消部署失败!"); } ``` --- ## 注意事项 1. **文件大小限制**: ZIP 文件大小不能超过 50MB,否则会导致内存溢出。 2. **同步轮询超时**: 同步轮询最多持续 5 分钟(60 次,每 5 秒一次),超时后会抛出异常。 3. **部署状态**: 部署状态包括 Queued、InProgress、Succeeded、Failed、Canceled,只有 Succeeded、Failed、Canceled 是终态。 4. **权限控制**: 所有接口都需要相应的权限,确保用户具有足够的权限才能调用。 5. **异步日志**: 部署操作会异步记录到 `datai_metadata_deploy_log` 表,可以通过该表查询部署历史。 6. **错误处理**: 所有错误都会转换为 `SalesforceOperationException`,包含详细的错误码和错误信息。 --- ## 相关文档 - [需求文档](../requirements/sub/2026-01-28-003-03-部署操作.md) - [设计文档](../design/2026-02-03-003-03-部署操作-设计.md) - [决策记录](../decisions/2026-02-03-003-03-ADR-通用部署接口设计.md) - [变更日志](../changelog/2026-02-06-003-03-changelog.md) - [会话记录](../sessions/2026-02-03-003-03-session.md) - [复盘文档](../retros/2026-02-06-003-03-retro.md) --- ## 版本历史 | 版本号 | 日期 | 变更内容 | 作者 | |--------|------|----------|------| | v1.0.0 | 2026-02-06 | 初始版本,实现部署 ZIP 包、同步轮询、状态查询、取消部署功能 | AI Assistant |