datai/docs/archive/prompts/023-version-rollback.md

1279 lines
35 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.

# Prompt First - 版本回溯功能
## 输入引用
引用相关的 docs 文档链接:
- [REQ-010-13.md](../requirements/REQ-010-13.md) - 版本回溯功能需求文档
- [0022-version-rollback.md](../decisions/adr/0022-version-rollback.md) - 版本回溯功能架构决策
- [REQ-010-7.md](../requirements/REQ-010-7.md) - 文件存储和解压处理需求文档
- [REQ-010-12.md](../requirements/REQ-010-12.md) - 文件哈希对比和增量检测需求文档
- [file/index.md](../api-docs/file/index.md) - 文件模块 API 文档索引(唯一真源)
## Context Maps
强制列出本次 Prompt 依赖的 Canvas 文件:
- [Authentication.canvas](../Authentication.canvas) - 项目架构视觉化展示
- **相关节点**: [集成核心](node_integration_core) - 提供与Salesforce的各种连接方式
## 目标
实现版本回溯功能,支持查看和恢复历史版本的元数据文件。包括版本历史记录、版本对比、版本恢复、版本回滚等功能。
## 输出格式
代码示例语言Java
## 约束
- **技术栈限制**: 必须基于现有的 Spring Boot 3 + MyBatis Plus 技术栈
- **架构约束**: 必须遵循 Authentication.canvas 中定义的架构和调用关系
- **模块约束**: 必须在 datai-salesforce-metadata 模块下实现
- **数据库约束**: 必须使用 MyBatis Plus 作为持久层框架
- **性能约束**: 版本对比和恢复性能必须满足要求
- **依赖约束**: 必须复用现有的 IFileStorageService、IMetadataRetrieveService、IMetadataDeployService 服务接口
## Rule Set
"请严格参考 @Authentication.canvas 中的状态机转移逻辑,不要自行发挥。"
**具体规则**
- 必须使用 Canvas 中定义的类名和方法名
- 必须遵循 Canvas 中定义的调用关系
- 必须参考 Canvas 中的流程图逻辑
## 验收标准
- **功能完整性**: 所有版本回溯功能能够正常工作
- **性能指标**: 版本对比和恢复性能满足要求
- **安全性**: 恢复和回滚操作安全可靠,有完整的日志记录
- **代码规范性**: 代码符合项目编码规范,有清晰的注释
- **可维护性**: 代码结构清晰,易于扩展和维护
- **可测试性**: 代码易于单元测试和集成测试
## 风险
- **版本记录风险**: 版本记录不完整可能导致无法恢复
- **对比风险**: 版本对比不准确可能导致误判
- **恢复风险**: 恢复操作失败可能导致数据不一致
- **回滚风险**: 回滚操作失败可能导致无法恢复
- **存储空间风险**: 版本历史记录过多可能占用大量存储空间
## 使用记录
| 日期 | 使用场景 | 输入参数 | 输出结果 | 反馈 | 改进措施 |
|------|---------|---------|---------|------|----------|
| 2026-01-19 | 实现版本回溯功能 | REQ-010-13.md, 0022-version-rollback.md | 完整的代码实现 | 无 | 无 |
---
## 核心代码实现
### 1. MetadataVersion 实体类
```java
package com.datai.salesforce.metadata.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 元数据版本实体类
*/
@Data
@TableName("datai_metadata_version")
public class MetadataVersion {
/**
* 主键ID
*/
@TableId(type = IdType.AUTO)
private Long id;
/**
* 版本号
*/
private String versionNumber;
/**
* 文件路径
*/
private String filePath;
/**
* 文件哈希值
*/
private String fileHash;
/**
* 文件内容
*/
private String fileContent;
/**
* 版本类型
*/
private String versionType;
/**
* 任务ID
*/
private Long taskId;
/**
* 组织配置ID
*/
private Long orgConfigId;
/**
* 版本时间
*/
private LocalDateTime versionTime;
/**
* 部门ID
*/
private Long deptId;
/**
* 创建人
*/
private String createBy;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新人
*/
private String updateBy;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 备注
*/
private String remark;
}
```
### 2. MetadataVersionMapper 接口
```java
package com.datai.salesforce.metadata.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDateTime;
import java.util.List;
/**
* 元数据版本 Mapper 接口
*/
@Mapper
public interface MetadataVersionMapper extends BaseMapper<MetadataVersion> {
/**
* 按时间查询版本
* @param startTime 开始时间
* @param endTime 结束时间
* @return 版本列表
*/
List<MetadataVersion> selectByTimeRange(@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime);
/**
* 按任务查询版本
* @param taskId 任务ID
* @return 版本列表
*/
List<MetadataVersion> selectByTaskId(@Param("taskId") Long taskId);
/**
* 按文件路径查询版本
* @param filePath 文件路径
* @return 版本列表
*/
List<MetadataVersion> selectByFilePath(@Param("filePath") String filePath);
/**
* 查询最新版本
* @param filePath 文件路径
* @return 最新版本
*/
MetadataVersion selectLatestVersion(@Param("filePath") String filePath);
/**
* 按时间查询版本(分页)
* @param page 分页参数
* @param startTime 开始时间
* @param endTime 结束时间
* @return 版本列表
*/
IPage<MetadataVersion> selectByTimeRangePage(Page<MetadataVersion> page,
@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime);
}
```
### 3. IMetadataVersionService 服务接口
```java
package com.datai.salesforce.metadata.service.version;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import java.time.LocalDateTime;
import java.util.List;
/**
* 元数据版本服务接口
*/
public interface IMetadataVersionService {
/**
* 创建版本
* @param version 版本信息
* @return 版本ID
*/
Long createVersion(MetadataVersion version);
/**
* 查询版本
* @param id 版本ID
* @return 版本信息
*/
MetadataVersion getVersion(Long id);
/**
* 按时间查询版本
* @param startTime 开始时间
* @param endTime 结束时间
* @return 版本列表
*/
List<MetadataVersion> getVersionsByTimeRange(LocalDateTime startTime, LocalDateTime endTime);
/**
* 按任务查询版本
* @param taskId 任务ID
* @return 版本列表
*/
List<MetadataVersion> getVersionsByTaskId(Long taskId);
/**
* 按文件路径查询版本
* @param filePath 文件路径
* @return 版本列表
*/
List<MetadataVersion> getVersionsByFilePath(String filePath);
/**
* 查询最新版本
* @param filePath 文件路径
* @return 最新版本
*/
MetadataVersion getLatestVersion(String filePath);
/**
* 按时间查询版本(分页)
* @param pageNum 页码
* @param pageSize 每页大小
* @param startTime 开始时间
* @param endTime 结束时间
* @return 版本列表
*/
IPage<MetadataVersion> getVersionsByTimeRangePage(int pageNum, int pageSize,
LocalDateTime startTime, LocalDateTime endTime);
/**
* 删除版本
* @param id 版本ID
* @return 删除结果
*/
boolean deleteVersion(Long id);
/**
* 批量删除版本
* @param ids 版本ID列表
* @return 删除结果
*/
boolean batchDeleteVersions(List<Long> ids);
}
```
### 4. MetadataVersionServiceImpl 服务实现
```java
package com.datai.salesforce.metadata.service.version.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import com.datai.salesforce.metadata.mapper.MetadataVersionMapper;
import com.datai.salesforce.metadata.service.version.IMetadataVersionService;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
* 元数据版本服务实现类
*/
@Service
public class MetadataVersionServiceImpl extends ServiceImpl<MetadataVersionMapper, MetadataVersion>
implements IMetadataVersionService {
@Override
public Long createVersion(MetadataVersion version) {
version.setCreateTime(LocalDateTime.now());
version.setUpdateTime(LocalDateTime.now());
save(version);
return version.getId();
}
@Override
public MetadataVersion getVersion(Long id) {
return getById(id);
}
@Override
public List<MetadataVersion> getVersionsByTimeRange(LocalDateTime startTime, LocalDateTime endTime) {
return baseMapper.selectByTimeRange(startTime, endTime);
}
@Override
public List<MetadataVersion> getVersionsByTaskId(Long taskId) {
return baseMapper.selectByTaskId(taskId);
}
@Override
public List<MetadataVersion> getVersionsByFilePath(String filePath) {
return baseMapper.selectByFilePath(filePath);
}
@Override
public MetadataVersion getLatestVersion(String filePath) {
return baseMapper.selectLatestVersion(filePath);
}
@Override
public IPage<MetadataVersion> getVersionsByTimeRangePage(int pageNum, int pageSize,
LocalDateTime startTime, LocalDateTime endTime) {
Page<MetadataVersion> page = new Page<>(pageNum, pageSize);
return baseMapper.selectByTimeRangePage(page, startTime, endTime);
}
@Override
public boolean deleteVersion(Long id) {
return removeById(id);
}
@Override
public boolean batchDeleteVersions(List<Long> ids) {
return removeByIds(ids);
}
}
```
### 5. IVersionComparisonService 服务接口
```java
package com.datai.salesforce.metadata.service.version;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import java.util.Map;
/**
* 版本对比服务接口
*/
public interface IVersionComparisonService {
/**
* 对比版本
* @param versionId1 版本ID1
* @param versionId2 版本ID2
* @return 对比结果
*/
Map<String, Object> compareVersions(Long versionId1, Long versionId2);
/**
* 对比文件内容
* @param content1 文件内容1
* @param content2 文件内容2
* @return 对比结果
*/
Map<String, Object> compareFileContent(String content1, String content2);
/**
* 对比文件哈希
* @param hash1 文件哈希1
* @param hash2 文件哈希2
* @return 对比结果
*/
Map<String, Object> compareFileHash(String hash1, String hash2);
}
```
### 6. VersionComparisonServiceImpl 服务实现
```java
package com.datai.salesforce.metadata.service.version.impl;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import com.datai.salesforce.metadata.service.version.IVersionComparisonService;
import com.datai.salesforce.metadata.service.version.IMetadataVersionService;
import com.google.diffmatchpatch.DiffMatchPatch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 版本对比服务实现类
*/
@Service
public class VersionComparisonServiceImpl implements IVersionComparisonService {
@Autowired
private IMetadataVersionService metadataVersionService;
private final DiffMatchPatch diffMatchPatch = new DiffMatchPatch();
@Override
public Map<String, Object> compareVersions(Long versionId1, Long versionId2) {
MetadataVersion version1 = metadataVersionService.getVersion(versionId1);
MetadataVersion version2 = metadataVersionService.getVersion(versionId2);
Map<String, Object> result = new HashMap<>();
result.put("version1", version1);
result.put("version2", version2);
result.put("contentDiff", compareFileContent(version1.getFileContent(), version2.getFileContent()));
result.put("hashDiff", compareFileHash(version1.getFileHash(), version2.getFileHash()));
return result;
}
@Override
public Map<String, Object> compareFileContent(String content1, String content2) {
LinkedList<DiffMatchPatch.Diff> diffs = diffMatchPatch.diffMain(content1, content2, false);
diffMatchPatch.diffCleanupSemantic(diffs);
Map<String, Object> result = new HashMap<>();
result.put("diffs", diffs);
result.put("hasChanges", diffs.size() > 1);
return result;
}
@Override
public Map<String, Object> compareFileHash(String hash1, String hash2) {
Map<String, Object> result = new HashMap<>();
result.put("hash1", hash1);
result.put("hash2", hash2);
result.put("isEqual", hash1.equals(hash2));
return result;
}
}
```
### 7. IVersionRecoveryService 服务接口
```java
package com.datai.salesforce.metadata.service.version;
import com.datai.salesforce.metadata.entity.MetadataVersion;
/**
* 版本恢复服务接口
*/
public interface IVersionRecoveryService {
/**
* 恢复版本
* @param versionId 版本ID
* @return 恢复结果
*/
String recoverVersion(Long versionId);
/**
* 恢复版本(异步)
* @param versionId 版本ID
* @return 恢复结果
*/
java.util.concurrent.Future<String> recoverVersionAsync(Long versionId);
}
```
### 8. VersionRecoveryServiceImpl 服务实现
```java
package com.datai.salesforce.metadata.service.version.impl;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import com.datai.salesforce.metadata.service.deploy.IMetadataDeployService;
import com.datai.salesforce.metadata.service.version.IVersionRecoveryService;
import com.datai.salesforce.metadata.service.version.IMetadataVersionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
/**
* 版本恢复服务实现类
*/
@Service
public class VersionRecoveryServiceImpl implements IVersionRecoveryService {
@Autowired
private IMetadataVersionService metadataVersionService;
@Autowired
private IMetadataDeployService metadataDeployService;
@Override
@Transactional
public String recoverVersion(Long versionId) {
MetadataVersion version = metadataVersionService.getVersion(versionId);
if (version == null) {
throw new RuntimeException("Version not found");
}
String result = metadataDeployService.deploy(version.getTaskId(),
version.getOrgConfigId(),
version.getFileContent());
return result;
}
@Override
@Async("deployExecutor")
public Future<String> recoverVersionAsync(Long versionId) {
return CompletableFuture.completedFuture(recoverVersion(versionId));
}
}
```
### 9. IVersionRollbackService 服务接口
```java
package com.datai.salesforce.metadata.service.version;
/**
* 版本回滚服务接口
*/
public interface IVersionRollbackService {
/**
* 回滚到上一个版本
* @param filePath 文件路径
* @return 回滚结果
*/
String rollbackToPreviousVersion(String filePath);
/**
* 回滚到上一个版本(异步)
* @param filePath 文件路径
* @return 回滚结果
*/
java.util.concurrent.Future<String> rollbackToPreviousVersionAsync(String filePath);
}
```
### 10. VersionRollbackServiceImpl 服务实现
```java
package com.datai.salesforce.metadata.service.version.impl;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import com.datai.salesforce.metadata.service.deploy.IMetadataDeployService;
import com.datai.salesforce.metadata.service.version.IVersionRollbackService;
import com.datai.salesforce.metadata.service.version.IMetadataVersionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
/**
* 版本回滚服务实现类
*/
@Service
public class VersionRollbackServiceImpl implements IVersionRollbackService {
@Autowired
private IMetadataVersionService metadataVersionService;
@Autowired
private IMetadataDeployService metadataDeployService;
@Override
@Transactional
public String rollbackToPreviousVersion(String filePath) {
List<MetadataVersion> versions = metadataVersionService.getVersionsByFilePath(filePath);
if (versions == null || versions.size() < 2) {
throw new RuntimeException("No previous version found");
}
MetadataVersion previousVersion = versions.get(1);
String result = metadataDeployService.deploy(previousVersion.getTaskId(),
previousVersion.getOrgConfigId(),
previousVersion.getFileContent());
return result;
}
@Override
@Async("deployExecutor")
public Future<String> rollbackToPreviousVersionAsync(String filePath) {
return CompletableFuture.completedFuture(rollbackToPreviousVersion(filePath));
}
}
```
### 11. VersionHistoryController 控制器
```java
package com.datai.salesforce.metadata.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import com.datai.salesforce.metadata.service.version.IMetadataVersionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
/**
* 版本历史控制器
*/
@RestController
@RequestMapping("/api/metadata/version-history")
public class VersionHistoryController {
@Autowired
private IMetadataVersionService metadataVersionService;
@PostMapping("/create")
public Map<String, Object> createVersion(@RequestBody MetadataVersion version) {
Long versionId = metadataVersionService.createVersion(version);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("versionId", versionId);
return response;
}
@GetMapping("/get/{id}")
public Map<String, Object> getVersion(@PathVariable Long id) {
MetadataVersion version = metadataVersionService.getVersion(id);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("version", version);
return response;
}
@GetMapping("/by-time-range")
public Map<String, Object> getVersionsByTimeRange(@RequestParam String startTime,
@RequestParam String endTime) {
LocalDateTime start = LocalDateTime.parse(startTime);
LocalDateTime end = LocalDateTime.parse(endTime);
List<MetadataVersion> versions = metadataVersionService.getVersionsByTimeRange(start, end);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("versions", versions);
return response;
}
@GetMapping("/by-task/{taskId}")
public Map<String, Object> getVersionsByTaskId(@PathVariable Long taskId) {
List<MetadataVersion> versions = metadataVersionService.getVersionsByTaskId(taskId);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("versions", versions);
return response;
}
@GetMapping("/by-file-path")
public Map<String, Object> getVersionsByFilePath(@RequestParam String filePath) {
List<MetadataVersion> versions = metadataVersionService.getVersionsByFilePath(filePath);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("versions", versions);
return response;
}
@GetMapping("/latest")
public Map<String, Object> getLatestVersion(@RequestParam String filePath) {
MetadataVersion version = metadataVersionService.getLatestVersion(filePath);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("version", version);
return response;
}
@GetMapping("/by-time-range-page")
public Map<String, Object> getVersionsByTimeRangePage(@RequestParam int pageNum,
@RequestParam int pageSize,
@RequestParam String startTime,
@RequestParam String endTime) {
LocalDateTime start = LocalDateTime.parse(startTime);
LocalDateTime end = LocalDateTime.parse(endTime);
IPage<MetadataVersion> versions = metadataVersionService.getVersionsByTimeRangePage(pageNum, pageSize, start, end);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("versions", versions);
return response;
}
@DeleteMapping("/delete/{id}")
public Map<String, Object> deleteVersion(@PathVariable Long id) {
boolean result = metadataVersionService.deleteVersion(id);
Map<String, Object> response = new HashMap<>();
response.put("success", result);
return response;
}
@DeleteMapping("/batch-delete")
public Map<String, Object> batchDeleteVersions(@RequestBody List<Long> ids) {
boolean result = metadataVersionService.batchDeleteVersions(ids);
Map<String, Object> response = new HashMap<>();
response.put("success", result);
return response;
}
}
```
### 12. VersionComparisonController 控制器
```java
package com.datai.salesforce.metadata.controller;
import com.datai.salesforce.metadata.service.version.IVersionComparisonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 版本对比控制器
*/
@RestController
@RequestMapping("/api/metadata/version-comparison")
public class VersionComparisonController {
@Autowired
private IVersionComparisonService versionComparisonService;
@PostMapping("/compare-versions")
public Map<String, Object> compareVersions(@RequestBody Map<String, Long> request) {
Long versionId1 = request.get("versionId1");
Long versionId2 = request.get("versionId2");
Map<String, Object> result = versionComparisonService.compareVersions(versionId1, versionId2);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("result", result);
return response;
}
@PostMapping("/compare-content")
public Map<String, Object> compareFileContent(@RequestBody Map<String, String> request) {
String content1 = request.get("content1");
String content2 = request.get("content2");
Map<String, Object> result = versionComparisonService.compareFileContent(content1, content2);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("result", result);
return response;
}
@PostMapping("/compare-hash")
public Map<String, Object> compareFileHash(@RequestBody Map<String, String> request) {
String hash1 = request.get("hash1");
String hash2 = request.get("hash2");
Map<String, Object> result = versionComparisonService.compareFileHash(hash1, hash2);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("result", result);
return response;
}
}
```
### 13. VersionRecoveryController 控制器
```java
package com.datai.salesforce.metadata.controller;
import com.datai.salesforce.metadata.service.version.IVersionRecoveryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 版本恢复控制器
*/
@RestController
@RequestMapping("/api/metadata/version-recovery")
public class VersionRecoveryController {
@Autowired
private IVersionRecoveryService versionRecoveryService;
@PostMapping("/recover")
public Map<String, Object> recoverVersion(@RequestBody Map<String, Long> request) {
Long versionId = request.get("versionId");
String result = versionRecoveryService.recoverVersion(versionId);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("result", result);
return response;
}
}
```
### 14. VersionRollbackController 控制器
```java
package com.datai.salesforce.metadata.controller;
import com.datai.salesforce.metadata.service.version.IVersionRollbackService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 版本回滚控制器
*/
@RestController
@RequestMapping("/api/metadata/version-rollback")
public class VersionRollbackController {
@Autowired
private IVersionRollbackService versionRollbackService;
@PostMapping("/rollback")
public Map<String, Object> rollbackToPreviousVersion(@RequestBody Map<String, String> request) {
String filePath = request.get("filePath");
String result = versionRollbackService.rollbackToPreviousVersion(filePath);
Map<String, Object> response = new HashMap<>();
response.put("success", true);
response.put("result", result);
return response;
}
}
```
### 15. DTO 类
```java
package com.datai.salesforce.metadata.dto;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
/**
* 版本历史创建请求
*/
@Data
public class VersionHistoryCreateRequest {
private String versionNumber;
private String filePath;
private String fileHash;
private String fileContent;
private String versionType;
private Long taskId;
private Long orgConfigId;
}
/**
* 版本历史创建响应
*/
@Data
public class VersionHistoryCreateResponse {
private boolean success;
private Long versionId;
}
/**
* 版本历史查询请求
*/
@Data
public class VersionHistoryQueryRequest {
private LocalDateTime startTime;
private LocalDateTime endTime;
private Long taskId;
private String filePath;
private int pageNum;
private int pageSize;
}
/**
* 版本历史查询响应
*/
@Data
public class VersionHistoryQueryResponse {
private boolean success;
private List<MetadataVersion> versions;
}
/**
* 版本对比请求
*/
@Data
public class VersionComparisonRequest {
private Long versionId1;
private Long versionId2;
}
/**
* 版本对比响应
*/
@Data
public class VersionComparisonResponse {
private boolean success;
private java.util.Map<String, Object> result;
}
/**
* 文件内容对比请求
*/
@Data
public class FileContentComparisonRequest {
private String content1;
private String content2;
}
/**
* 文件内容对比响应
*/
@Data
public class FileContentComparisonResponse {
private boolean success;
private java.util.Map<String, Object> result;
}
/**
* 文件哈希对比请求
*/
@Data
public class FileHashComparisonRequest {
private String hash1;
private String hash2;
}
/**
* 文件哈希对比响应
*/
@Data
public class FileHashComparisonResponse {
private boolean success;
private java.util.Map<String, Object> result;
}
/**
* 版本恢复请求
*/
@Data
public class VersionRecoveryRequest {
private Long versionId;
}
/**
* 版本恢复响应
*/
@Data
public class VersionRecoveryResponse {
private boolean success;
private String result;
}
/**
* 版本回滚请求
*/
@Data
public class VersionRollbackRequest {
private String filePath;
}
/**
* 版本回滚响应
*/
@Data
public class VersionRollbackResponse {
private boolean success;
private String result;
}
```
### 16. 异常类
```java
package com.datai.salesforce.metadata.exception;
/**
* 版本历史异常
*/
public class VersionHistoryException extends RuntimeException {
public VersionHistoryException(String message) {
super(message);
}
public VersionHistoryException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* 版本对比异常
*/
public class VersionComparisonException extends RuntimeException {
public VersionComparisonException(String message) {
super(message);
}
public VersionComparisonException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* 版本恢复异常
*/
public class VersionRecoveryException extends RuntimeException {
public VersionRecoveryException(String message) {
super(message);
}
public VersionRecoveryException(String message, Throwable cause) {
super(message, cause);
}
}
/**
* 版本回滚异常
*/
public class VersionRollbackException extends RuntimeException {
public VersionRollbackException(String message) {
super(message);
}
public VersionRollbackException(String message, Throwable cause) {
super(message, cause);
}
}
```
---
## 单元测试
### MetadataVersionServiceImplTest
```java
package com.datai.salesforce.metadata.service.version.impl;
import com.datai.salesforce.metadata.entity.MetadataVersion;
import com.datai.salesforce.metadata.service.version.IMetadataVersionService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class MetadataVersionServiceImplTest {
@Autowired
private IMetadataVersionService metadataVersionService;
@Test
void testCreateVersion() {
MetadataVersion version = new MetadataVersion();
version.setVersionNumber("v1.0.0");
version.setFilePath("test.txt");
version.setFileHash("abc123");
version.setFileContent("test content");
version.setVersionType("RETRIEVE");
version.setTaskId(1L);
version.setOrgConfigId(1L);
version.setVersionTime(LocalDateTime.now());
Long versionId = metadataVersionService.createVersion(version);
assertNotNull(versionId);
assertTrue(versionId > 0);
}
@Test
void testGetVersion() {
MetadataVersion version = metadataVersionService.getVersion(1L);
assertNotNull(version);
}
}
```
### VersionComparisonServiceImplTest
```java
package com.datai.salesforce.metadata.service.version.impl;
import com.datai.salesforce.metadata.service.version.IVersionComparisonService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class VersionComparisonServiceImplTest {
@Autowired
private IVersionComparisonService versionComparisonService;
@Test
void testCompareFileContent() {
String content1 = "Hello World";
String content2 = "Hello Java";
Map<String, Object> result = versionComparisonService.compareFileContent(content1, content2);
assertNotNull(result);
assertTrue((Boolean) result.get("hasChanges"));
}
@Test
void testCompareFileHash() {
String hash1 = "abc123";
String hash2 = "def456";
Map<String, Object> result = versionComparisonService.compareFileHash(hash1, hash2);
assertNotNull(result);
assertFalse((Boolean) result.get("isEqual"));
}
}
```
---
## 配置文件
### application.yml
```yaml
spring:
task:
execution:
pool:
core-size: 5
max-size: 10
queue-capacity: 100
thread-name-prefix: version-executor-
version-rollback:
max-versions: 100
retention-days: 30
```
---
## 数据库表
### datai_metadata_version
```sql
CREATE TABLE `datai_metadata_version` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`version_number` varchar(50) NOT NULL COMMENT '版本号',
`file_path` varchar(500) NOT NULL COMMENT '文件路径',
`file_hash` varchar(64) DEFAULT NULL COMMENT '文件哈希值',
`file_content` text COMMENT '文件内容',
`version_type` varchar(20) NOT NULL COMMENT '版本类型',
`task_id` bigint DEFAULT NULL COMMENT '任务ID',
`org_config_id` bigint DEFAULT NULL COMMENT '组织配置ID',
`version_time` datetime NOT NULL COMMENT '版本时间',
`dept_id` bigint DEFAULT NULL COMMENT '部门ID',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `idx_task_id` (`task_id`),
KEY `idx_org_config_id` (`org_config_id`),
KEY `idx_file_path` (`file_path`),
KEY `idx_version_time` (`version_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='元数据版本表';
```
---
## 总结
本 Prompt 提供了版本回溯功能的完整实现,包括:
1. **版本历史记录** - 记录每次拉取和部署的版本
2. **版本对比** - 对比不同版本的元数据文件
3. **版本恢复** - 恢复到指定的历史版本
4. **版本回滚** - 回滚到上一个版本
所有代码都遵循 Spring Boot 3 + MyBatis Plus 技术栈,复用现有的服务接口,保持代码一致性。