datai/datai-scenes/datai-scene-salesforce/docs/prompts/023-version-rollback.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

35 KiB
Raw Blame History

Prompt First - 版本回溯功能

输入引用

引用相关的 docs 文档链接:

Context Maps

强制列出本次 Prompt 依赖的 Canvas 文件:

目标

实现版本回溯功能,支持查看和恢复历史版本的元数据文件。包括版本历史记录、版本对比、版本恢复、版本回滚等功能。

输出格式

代码示例语言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 实体类

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 接口

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 服务接口

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 服务实现

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 服务接口

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 服务实现

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 服务接口

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 服务实现

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 服务接口

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 服务实现

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 控制器

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 控制器

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 控制器

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 控制器

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 类

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. 异常类

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

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

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

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

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 技术栈,复用现有的服务接口,保持代码一致性。