# 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 { /** * 按时间查询版本 * @param startTime 开始时间 * @param endTime 结束时间 * @return 版本列表 */ List selectByTimeRange(@Param("startTime") LocalDateTime startTime, @Param("endTime") LocalDateTime endTime); /** * 按任务查询版本 * @param taskId 任务ID * @return 版本列表 */ List selectByTaskId(@Param("taskId") Long taskId); /** * 按文件路径查询版本 * @param filePath 文件路径 * @return 版本列表 */ List selectByFilePath(@Param("filePath") String filePath); /** * 查询最新版本 * @param filePath 文件路径 * @return 最新版本 */ MetadataVersion selectLatestVersion(@Param("filePath") String filePath); /** * 按时间查询版本(分页) * @param page 分页参数 * @param startTime 开始时间 * @param endTime 结束时间 * @return 版本列表 */ IPage selectByTimeRangePage(Page 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 getVersionsByTimeRange(LocalDateTime startTime, LocalDateTime endTime); /** * 按任务查询版本 * @param taskId 任务ID * @return 版本列表 */ List getVersionsByTaskId(Long taskId); /** * 按文件路径查询版本 * @param filePath 文件路径 * @return 版本列表 */ List getVersionsByFilePath(String filePath); /** * 查询最新版本 * @param filePath 文件路径 * @return 最新版本 */ MetadataVersion getLatestVersion(String filePath); /** * 按时间查询版本(分页) * @param pageNum 页码 * @param pageSize 每页大小 * @param startTime 开始时间 * @param endTime 结束时间 * @return 版本列表 */ IPage getVersionsByTimeRangePage(int pageNum, int pageSize, LocalDateTime startTime, LocalDateTime endTime); /** * 删除版本 * @param id 版本ID * @return 删除结果 */ boolean deleteVersion(Long id); /** * 批量删除版本 * @param ids 版本ID列表 * @return 删除结果 */ boolean batchDeleteVersions(List 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 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 getVersionsByTimeRange(LocalDateTime startTime, LocalDateTime endTime) { return baseMapper.selectByTimeRange(startTime, endTime); } @Override public List getVersionsByTaskId(Long taskId) { return baseMapper.selectByTaskId(taskId); } @Override public List getVersionsByFilePath(String filePath) { return baseMapper.selectByFilePath(filePath); } @Override public MetadataVersion getLatestVersion(String filePath) { return baseMapper.selectLatestVersion(filePath); } @Override public IPage getVersionsByTimeRangePage(int pageNum, int pageSize, LocalDateTime startTime, LocalDateTime endTime) { Page 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 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 compareVersions(Long versionId1, Long versionId2); /** * 对比文件内容 * @param content1 文件内容1 * @param content2 文件内容2 * @return 对比结果 */ Map compareFileContent(String content1, String content2); /** * 对比文件哈希 * @param hash1 文件哈希1 * @param hash2 文件哈希2 * @return 对比结果 */ Map 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 compareVersions(Long versionId1, Long versionId2) { MetadataVersion version1 = metadataVersionService.getVersion(versionId1); MetadataVersion version2 = metadataVersionService.getVersion(versionId2); Map 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 compareFileContent(String content1, String content2) { LinkedList diffs = diffMatchPatch.diffMain(content1, content2, false); diffMatchPatch.diffCleanupSemantic(diffs); Map result = new HashMap<>(); result.put("diffs", diffs); result.put("hasChanges", diffs.size() > 1); return result; } @Override public Map compareFileHash(String hash1, String hash2) { Map 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 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 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 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 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 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 createVersion(@RequestBody MetadataVersion version) { Long versionId = metadataVersionService.createVersion(version); Map response = new HashMap<>(); response.put("success", true); response.put("versionId", versionId); return response; } @GetMapping("/get/{id}") public Map getVersion(@PathVariable Long id) { MetadataVersion version = metadataVersionService.getVersion(id); Map response = new HashMap<>(); response.put("success", true); response.put("version", version); return response; } @GetMapping("/by-time-range") public Map getVersionsByTimeRange(@RequestParam String startTime, @RequestParam String endTime) { LocalDateTime start = LocalDateTime.parse(startTime); LocalDateTime end = LocalDateTime.parse(endTime); List versions = metadataVersionService.getVersionsByTimeRange(start, end); Map response = new HashMap<>(); response.put("success", true); response.put("versions", versions); return response; } @GetMapping("/by-task/{taskId}") public Map getVersionsByTaskId(@PathVariable Long taskId) { List versions = metadataVersionService.getVersionsByTaskId(taskId); Map response = new HashMap<>(); response.put("success", true); response.put("versions", versions); return response; } @GetMapping("/by-file-path") public Map getVersionsByFilePath(@RequestParam String filePath) { List versions = metadataVersionService.getVersionsByFilePath(filePath); Map response = new HashMap<>(); response.put("success", true); response.put("versions", versions); return response; } @GetMapping("/latest") public Map getLatestVersion(@RequestParam String filePath) { MetadataVersion version = metadataVersionService.getLatestVersion(filePath); Map response = new HashMap<>(); response.put("success", true); response.put("version", version); return response; } @GetMapping("/by-time-range-page") public Map getVersionsByTimeRangePage(@RequestParam int pageNum, @RequestParam int pageSize, @RequestParam String startTime, @RequestParam String endTime) { LocalDateTime start = LocalDateTime.parse(startTime); LocalDateTime end = LocalDateTime.parse(endTime); IPage versions = metadataVersionService.getVersionsByTimeRangePage(pageNum, pageSize, start, end); Map response = new HashMap<>(); response.put("success", true); response.put("versions", versions); return response; } @DeleteMapping("/delete/{id}") public Map deleteVersion(@PathVariable Long id) { boolean result = metadataVersionService.deleteVersion(id); Map response = new HashMap<>(); response.put("success", result); return response; } @DeleteMapping("/batch-delete") public Map batchDeleteVersions(@RequestBody List ids) { boolean result = metadataVersionService.batchDeleteVersions(ids); Map 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 compareVersions(@RequestBody Map request) { Long versionId1 = request.get("versionId1"); Long versionId2 = request.get("versionId2"); Map result = versionComparisonService.compareVersions(versionId1, versionId2); Map response = new HashMap<>(); response.put("success", true); response.put("result", result); return response; } @PostMapping("/compare-content") public Map compareFileContent(@RequestBody Map request) { String content1 = request.get("content1"); String content2 = request.get("content2"); Map result = versionComparisonService.compareFileContent(content1, content2); Map response = new HashMap<>(); response.put("success", true); response.put("result", result); return response; } @PostMapping("/compare-hash") public Map compareFileHash(@RequestBody Map request) { String hash1 = request.get("hash1"); String hash2 = request.get("hash2"); Map result = versionComparisonService.compareFileHash(hash1, hash2); Map 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 recoverVersion(@RequestBody Map request) { Long versionId = request.get("versionId"); String result = versionRecoveryService.recoverVersion(versionId); Map 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 rollbackToPreviousVersion(@RequestBody Map request) { String filePath = request.get("filePath"); String result = versionRollbackService.rollbackToPreviousVersion(filePath); Map 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 versions; } /** * 版本对比请求 */ @Data public class VersionComparisonRequest { private Long versionId1; private Long versionId2; } /** * 版本对比响应 */ @Data public class VersionComparisonResponse { private boolean success; private java.util.Map result; } /** * 文件内容对比请求 */ @Data public class FileContentComparisonRequest { private String content1; private String content2; } /** * 文件内容对比响应 */ @Data public class FileContentComparisonResponse { private boolean success; private java.util.Map result; } /** * 文件哈希对比请求 */ @Data public class FileHashComparisonRequest { private String hash1; private String hash2; } /** * 文件哈希对比响应 */ @Data public class FileHashComparisonResponse { private boolean success; private java.util.Map 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 result = versionComparisonService.compareFileContent(content1, content2); assertNotNull(result); assertTrue((Boolean) result.get("hasChanges")); } @Test void testCompareFileHash() { String hash1 = "abc123"; String hash2 = "def456"; Map 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 技术栈,复用现有的服务接口,保持代码一致性。