12 KiB
12 KiB
Architecture Decision Record - 元数据任务定义管理
元数据
- ADR 编号: ADR-0013
- 创建日期: 2026-01-18
- 状态: 已接受
- 决策者: Datai Team
- 相关需求: REQ-010-4 - 元数据任务定义管理
上下文和问题陈述
背景
REQ-010-4 需求要求实现元数据任务定义的完整管理功能,包括任务的增删改查、package.xml内容配置、API版本选择、调度类型选择、Cron表达式配置、任务验证等。
问题
需要设计元数据任务定义管理的技术方案,解决以下关键问题:
- 数据模型设计: 如何设计元数据任务定义的数据模型,支持任务配置、package.xml内容、API版本、调度类型等
- package.xml管理: 如何管理和验证package.xml内容,确保符合Salesforce Metadata API规范
- 调度配置: 如何支持Manual和Cron两种调度类型,如何验证Cron表达式
- 任务验证: 如何验证package.xml和调度配置,确保任务可执行
- API设计: 如何设计RESTful API接口,支持任务的CRUD操作
决策驱动因素
技术约束
- 必须基于现有的Spring Boot 3 + Vue 3技术栈
- 必须使用MyBatis Plus作为持久层框架
- 必须遵循Authentication.canvas中定义的架构和调用关系
- 必须在datai-salesforce-metadata模块下实现
业务需求
- 支持任务的增删改查功能
- 支持package.xml内容配置和验证
- 支持API版本选择和验证
- 支持调度类型选择(Manual/Cron)
- 支持Cron表达式配置和验证
- 支持任务验证功能
非功能需求
- 代码符合项目编码规范,有清晰的注释
- 操作界面友好易用,提供清晰的错误信息
- 代码结构清晰,易于扩展和维护
考虑的选项
选项1:使用XML文件存储package.xml
描述: 将package.xml内容作为XML字符串存储在数据库中,使用XML解析库进行验证。
优点:
- 实现简单,直接存储XML内容
- 易于验证XML格式
- 符合Salesforce Metadata API规范
缺点:
- XML字符串可能很长,占用数据库空间
- 需要额外的XML解析库
- 难以可视化编辑
风险评估: 中
选项2:使用JSON格式存储package.xml配置
描述: 将package.xml内容解析为JSON格式存储在数据库中,使用时再转换为XML。
优点:
- JSON格式更易于处理和验证
- 可以使用现有的JSON工具库
- 便于前端可视化编辑
缺点:
- 需要JSON和XML之间的转换
- 可能丢失XML的某些特性
- 转换过程可能引入错误
风险评估: 中
选项3:使用结构化数据存储package.xml
描述: 将package.xml内容解析为结构化数据(元数据类型列表),存储在关联表中。
优点:
- 数据结构清晰,易于查询和管理
- 便于前端可视化编辑
- 可以支持更复杂的验证逻辑
缺点:
- 实现复杂,需要设计多个关联表
- 需要处理XML和结构化数据之间的转换
- 可能无法支持所有XML特性
风险评估: 高
决策结果
选定方案:选项1 - 使用XML文件存储package.xml
理由:
- 符合规范: 直接存储XML内容,完全符合Salesforce Metadata API规范,避免转换过程中的错误
- 实现简单: 实现复杂度最低,开发周期短
- 验证准确: 可以直接使用XML解析库验证XML格式,验证结果准确
- 扩展性好: 未来如果需要支持更复杂的配置,可以在此基础上扩展
拒绝其他选项的理由
- 选项2: JSON和XML之间的转换可能引入错误,且无法完全保留XML的所有特性
- 选项3: 实现复杂度高,开发周期长,且可能无法支持所有XML特性
技术方案
数据模型设计
主表:datai_meta_task
CREATE TABLE `datai_meta_task` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '任务ID',
`task_name` varchar(255) NOT NULL COMMENT '任务名称',
`task_type` varchar(50) NOT NULL COMMENT '任务类型(retrieve/deploy)',
`org_config_id` bigint NOT NULL COMMENT '组织配置ID',
`package_xml` longtext COMMENT 'package.xml内容',
`api_version` varchar(20) NOT NULL COMMENT 'API版本',
`schedule_type` varchar(20) NOT NULL COMMENT '调度类型(Manual/Cron)',
`cron_expression` varchar(100) COMMENT 'Cron表达式',
`status` varchar(20) NOT NULL COMMENT '任务状态(Active/Inactive)',
`description` varchar(500) COMMENT '任务描述',
`created_by` varchar(100) COMMENT '创建人',
`created_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_by` varchar(100) COMMENT '更新人',
`updated_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_org_config_id` (`org_config_id`),
KEY `idx_task_type` (`task_type`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='元数据任务定义表';
API设计
1. 创建任务
- 接口路径: POST /metadata/task
- 请求参数:
{ "taskName": "任务名称", "taskType": "retrieve", "orgConfigId": 1, "packageXml": "<?xml version=\"1.0\"...", "apiVersion": "58.0", "scheduleType": "Cron", "cronExpression": "0 0 0 * * ?", "description": "任务描述" } - 响应: 返回创建的任务ID
2. 查询任务列表
- 接口路径: GET /metadata/task/list
- 请求参数:
- pageNum: 页码
- pageSize: 每页大小
- taskName: 任务名称(可选)
- taskType: 任务类型(可选)
- status: 任务状态(可选)
- 响应: 返回任务列表和分页信息
3. 查询任务详情
- 接口路径: GET /metadata/task/{id}
- 响应: 返回任务详细信息
4. 更新任务
- 接口路径: PUT /metadata/task/{id}
- 请求参数: 同创建任务
- 响应: 返回更新结果
5. 删除任务
- 接口路径: DELETE /metadata/task/{id}
- 响应: 返回删除结果
6. 验证任务
- 接口路径: POST /metadata/task/{id}/validate
- 响应: 返回验证结果
package.xml验证
验证规则
- 格式验证: 使用XML解析库验证XML格式是否正确
- 元数据类型验证: 验证package.xml中配置的元数据类型是否在支持的类型列表中
- 通配符验证: 验证通配符使用是否正确
- API版本验证: 验证API版本是否在支持的版本列表中
验证实现
public class PackageXmlValidator {
public ValidationResult validate(String packageXml) {
try {
// 解析XML
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(packageXml)));
// 验证根元素
NodeList types = doc.getElementsByTagName("types");
if (types.getLength() == 0) {
return ValidationResult.error("package.xml必须包含types元素");
}
// 验证元数据类型
for (int i = 0; i < types.getLength(); i++) {
Element type = (Element) types.item(i);
String typeName = type.getTextContent();
if (!isSupportedMetadataType(typeName)) {
return ValidationResult.error("不支持的元数据类型: " + typeName);
}
}
return ValidationResult.success();
} catch (Exception e) {
return ValidationResult.error("package.xml格式错误: " + e.getMessage());
}
}
private boolean isSupportedMetadataType(String typeName) {
// 检查元数据类型是否在支持的类型列表中
return MetadataTypeRegistry.contains(typeName);
}
}
Cron表达式验证
验证规则
- 格式验证: 使用Cron表达式解析库验证Cron表达式格式是否正确
- 解析验证: 验证Cron表达式是否能够正确解析
- 预览验证: 提供Cron表达式预览,显示下次执行时间
验证实现
public class CronExpressionValidator {
public ValidationResult validate(String cronExpression) {
try {
// 使用Quartz的CronExpression验证
CronExpression cron = new CronExpression(cronExpression);
// 验证是否有效
if (!cron.isValid()) {
return ValidationResult.error("Cron表达式格式错误");
}
// 验证是否能够计算下次执行时间
Date nextValidTime = cron.getNextValidTimeAfter(new Date());
if (nextValidTime == null) {
return ValidationResult.error("Cron表达式无法计算下次执行时间");
}
return ValidationResult.success(nextValidTime);
} catch (Exception e) {
return ValidationResult.error("Cron表达式解析错误: " + e.getMessage());
}
}
}
调度类型管理
枚举定义
public enum ScheduleType {
MANUAL("Manual", "手动调度"),
CRON("Cron", "Cron调度");
private final String code;
private final String description;
ScheduleType(String code, String description) {
this.code = code;
this.description = description;
}
public String getCode() {
return code;
}
public String getDescription() {
return description;
}
}
API版本管理
版本列表
public class MetadataApiVersion {
private static final List<String> SUPPORTED_VERSIONS = Arrays.asList(
"58.0", "57.0", "56.0", "55.0", "54.0"
);
public static List<String> getSupportedVersions() {
return SUPPORTED_VERSIONS;
}
public static boolean isSupported(String version) {
return SUPPORTED_VERSIONS.contains(version);
}
}
后果
正面影响
- 开发效率: 实现简单,开发周期短
- 维护性: 代码结构清晰,易于维护
- 扩展性: 未来可以在此基础上扩展更多功能
- 准确性: 直接存储XML,避免转换错误
负面影响
- 存储空间: XML字符串可能占用较多数据库空间
- 可视化: 需要额外的XML编辑器组件支持可视化编辑
- 查询性能: XML字符串查询可能不如结构化数据高效
回滚策略
如果本决策在实践中出现问题,可以考虑回滚到选项2或选项3:
- 回滚条件: 如果XML字符串存储导致严重的性能问题或存储空间不足
- 回滚步骤:
- 设计结构化数据模型
- 实现XML和结构化数据之间的转换
- 迁移现有数据
- 回滚风险: 数据迁移可能引入新的错误
相关文档
- REQ-010-4 - 元数据任务定义管理需求
- metadata-module.md - Salesforce Metadata API 模块说明
- file/index.md - 文件模块 API 文档索引
- Authentication.canvas - 项目架构视觉化展示
审核记录
| 日期 | 审核人 | 审核结果 | 审核意见 |
|---|---|---|---|
| 2026-01-18 | Datai Team | 已接受 | 方案合理,可以实施 |
变更历史
| 日期 | 版本 | 变更内容 | 变更人 |
|---|---|---|---|
| 2026-01-18 | v1.0.0 | 初始版本 | Datai Team |