datai/datai-scenes/datai-scene-salesforce/docs/decisions/adr/0013-task-definition-management.md
Kris 2e6f087732 docs: 完成REQ-010-17和REQ-010-2的文档创建
- 完成REQ-010-17(性能优化和限流处理)的所有6个阶段
  - 创建ADR文档:0026-performance-optimization.md
  - 创建Prompt文档:027-performance-optimization.md
  - 创建会话记录:20260119-performance-optimization.md
  - 创建变更记录:20260119-performance-optimization.md
  - 创建复盘报告:20260119-performance-optimization-retro.md
  - 更新index.md和CHANGELOG.md

- 完成REQ-010-2(基础实体类和Mapper创建)的前3个阶段
  - 更新ADR文档:0011-entity-mapper-create.md
  - 创建Prompt文档:002-entity-mapper-create.md
  - 更新index.md

所有文档均按照SSOT方法论创建,包括需求定义、架构决策、提示词资产化、执行会话、变更记录和闭环复盘。
2026-01-19 10:06:09 +08:00

376 lines
12 KiB
Markdown
Raw 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.

# Architecture Decision Record - 元数据任务定义管理
## 元数据
- **ADR 编号**: ADR-0013
- **创建日期**: 2026-01-18
- **状态**: 已接受
- **决策者**: Datai Team
- **相关需求**: [REQ-010-4](../requirements/REQ-010-4.md) - 元数据任务定义管理
## 上下文和问题陈述
### 背景
REQ-010-4 需求要求实现元数据任务定义的完整管理功能包括任务的增删改查、package.xml内容配置、API版本选择、调度类型选择、Cron表达式配置、任务验证等。
### 问题
需要设计元数据任务定义管理的技术方案,解决以下关键问题:
1. **数据模型设计**: 如何设计元数据任务定义的数据模型支持任务配置、package.xml内容、API版本、调度类型等
2. **package.xml管理**: 如何管理和验证package.xml内容确保符合Salesforce Metadata API规范
3. **调度配置**: 如何支持Manual和Cron两种调度类型如何验证Cron表达式
4. **任务验证**: 如何验证package.xml和调度配置确保任务可执行
5. **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
**理由**:
1. **符合规范**: 直接存储XML内容完全符合Salesforce Metadata API规范避免转换过程中的错误
2. **实现简单**: 实现复杂度最低,开发周期短
3. **验证准确**: 可以直接使用XML解析库验证XML格式验证结果准确
4. **扩展性好**: 未来如果需要支持更复杂的配置,可以在此基础上扩展
### 拒绝其他选项的理由
- **选项2**: JSON和XML之间的转换可能引入错误且无法完全保留XML的所有特性
- **选项3**: 实现复杂度高开发周期长且可能无法支持所有XML特性
## 技术方案
### 数据模型设计
#### 主表datai_meta_task
```sql
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
- **请求参数**:
```json
{
"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验证
#### 验证规则
1. **格式验证**: 使用XML解析库验证XML格式是否正确
2. **元数据类型验证**: 验证package.xml中配置的元数据类型是否在支持的类型列表中
3. **通配符验证**: 验证通配符使用是否正确
4. **API版本验证**: 验证API版本是否在支持的版本列表中
#### 验证实现
```java
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表达式验证
#### 验证规则
1. **格式验证**: 使用Cron表达式解析库验证Cron表达式格式是否正确
2. **解析验证**: 验证Cron表达式是否能够正确解析
3. **预览验证**: 提供Cron表达式预览显示下次执行时间
#### 验证实现
```java
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());
}
}
}
```
### 调度类型管理
#### 枚举定义
```java
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版本管理
#### 版本列表
```java
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);
}
}
```
## 后果
### 正面影响
1. **开发效率**: 实现简单,开发周期短
2. **维护性**: 代码结构清晰,易于维护
3. **扩展性**: 未来可以在此基础上扩展更多功能
4. **准确性**: 直接存储XML避免转换错误
### 负面影响
1. **存储空间**: XML字符串可能占用较多数据库空间
2. **可视化**: 需要额外的XML编辑器组件支持可视化编辑
3. **查询性能**: XML字符串查询可能不如结构化数据高效
## 回滚策略
如果本决策在实践中出现问题可以考虑回滚到选项2或选项3
1. **回滚条件**: 如果XML字符串存储导致严重的性能问题或存储空间不足
2. **回滚步骤**:
- 设计结构化数据模型
- 实现XML和结构化数据之间的转换
- 迁移现有数据
3. **回滚风险**: 数据迁移可能引入新的错误
## 相关文档
- [REQ-010-4](../requirements/REQ-010-4.md) - 元数据任务定义管理需求
- [metadata-module.md](../reference-code/com/docs/metadata-module.md) - Salesforce Metadata API 模块说明
- [file/index.md](../api-docs/file/index.md) - 文件模块 API 文档索引
- [Authentication.canvas](../Authentication.canvas) - 项目架构视觉化展示
## 审核记录
| 日期 | 审核人 | 审核结果 | 审核意见 |
|------|--------|----------|----------|
| 2026-01-18 | Datai Team | 已接受 | 方案合理,可以实施 |
## 变更历史
| 日期 | 版本 | 变更内容 | 变更人 |
|------|------|---------|--------|
| 2026-01-18 | v1.0.0 | 初始版本 | Datai Team |