- 完成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方法论创建,包括需求定义、架构决策、提示词资产化、执行会话、变更记录和闭环复盘。
27 KiB
会话记录 - 元数据组件索引和查询
现状
当前项目已经实现了文件存储和解压处理(REQ-010-7),包括 Zip 文件存储、文件解压、文件路径管理。现在需要实现元数据组件索引和查询功能,包括组件索引创建、组件查询、组件详情查看、组件统计。
目标
实现元数据组件索引和查询功能,包括组件索引创建、组件查询、组件详情查看、组件统计。支持按类型、名称、版本等条件查询元数据组件。
输入链接
- REQ-010-11.md - 元数据组件索引和查询需求文档
- 0020-metadata-component-index.md - 元数据组件索引和查询架构决策
- REQ-010-7.md - 文件存储和解压处理需求文档
- 0016-file-storage-and-extract.md - 文件存储和解压处理架构决策
- file/index.md - 文件模块 API 文档索引
Prompt 文件
- 021-metadata-component-index.md - 元数据组件索引和查询实现提示词
Context Snapshot
记录本次会话参考了哪些 Canvas 节点:
- Authentication.canvas - 项目架构视觉化展示
- 参考节点: 集成核心 - 提供与Salesforce的各种连接方式
- 参考节点: IMetadataApiService - 元数据API服务接口
- 参考节点: MetadataApiClient - Metadata API客户端
- 快照时间: 2026-01-19 12:00:00
执行过程
1. 创建 MetadataComponentIndexController 控制器
执行内容: 创建 MetadataComponentIndexController 控制器,提供 8 个 RESTful API 接口,支持组件索引创建、组件查询、组件详情查看、组件统计。
关键代码:
@RestController
@RequestMapping("/metadata/component")
public class MetadataComponentIndexController {
@Autowired
private IMetadataComponentIndexService componentIndexService;
@Autowired
private IMetadataComponentQueryService componentQueryService;
@Autowired
private IMetadataComponentDetailService componentDetailService;
@Autowired
private IMetadataComponentStatisticsService componentStatisticsService;
@PostMapping("/index")
public ComponentIndexResponse createIndex(@RequestBody ComponentIndexRequest request) {
return componentIndexService.createIndex(request);
}
@GetMapping("/query")
public ComponentQueryResponse queryComponents(
@RequestParam(required = false) String type,
@RequestParam(required = false) String name,
@RequestParam(required = false) String version,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "10") int size) {
ComponentQueryRequest request = new ComponentQueryRequest();
request.setType(type);
request.setName(name);
request.setVersion(version);
request.setPage(page);
request.setSize(size);
return componentQueryService.queryComponents(request);
}
@GetMapping("/detail/{id}")
public ComponentDetailResponse getComponentDetail(@PathVariable Long id) {
return componentDetailService.getComponentDetail(id);
}
@GetMapping("/detail/{id}/content")
public String getComponentContent(@PathVariable Long id) {
return componentDetailService.getComponentContent(id);
}
@GetMapping("/detail/{id}/dependencies")
public ComponentDetailResponse getComponentDependencies(@PathVariable Long id) {
return componentDetailService.getComponentDependencies(id);
}
@GetMapping("/statistics")
public ComponentStatisticsResponse getStatistics(
@RequestParam(required = false) String type,
@RequestParam(required = false) String version,
@RequestParam(required = false) Long orgConfigId) {
return componentStatisticsService.getStatistics(type, version, orgConfigId);
}
@GetMapping("/statistics/type-distribution")
public ComponentTypeDistributionResponse getTypeDistribution(
@RequestParam(required = false) Long orgConfigId) {
return componentStatisticsService.getTypeDistribution(orgConfigId);
}
@GetMapping("/statistics/version-distribution")
public ComponentVersionDistributionResponse getVersionDistribution(
@RequestParam(required = false) Long orgConfigId) {
return componentStatisticsService.getVersionDistribution(orgConfigId);
}
}
遇到的问题: 无
解决方案: 无
2. 创建 IMetadataComponentIndexService 服务接口
执行内容: 创建 IMetadataComponentIndexService 服务接口,定义组件索引服务接口方法。
关键代码:
public interface IMetadataComponentIndexService {
ComponentIndexResponse createIndex(ComponentIndexRequest request);
}
遇到的问题: 无
解决方案: 无
3. 创建 MetadataComponentIndexServiceImpl 服务实现
执行内容: 创建 MetadataComponentIndexServiceImpl 服务实现,实现组件索引服务接口方法,支持异步索引创建。
关键代码:
@Service
public class MetadataComponentIndexServiceImpl implements IMetadataComponentIndexService {
@Autowired
private MetadataComponentIndexMapper componentIndexMapper;
@Autowired
private IFileStorageService fileStorageService;
@Autowired
private ApexClassParser apexClassParser;
@Autowired
private VisualforcePageParser visualforcePageParser;
@Autowired
private CustomObjectParser customObjectParser;
@Autowired
private CustomFieldParser customFieldParser;
@Override
@Async("indexExecutor")
@Transactional
public ComponentIndexResponse createIndex(ComponentIndexRequest request) {
File extractPath = fileStorageService.getExtractPath(request.getTaskId());
List<MetadataComponentIndex> components = new ArrayList<>();
components.addAll(apexClassParser.parse(extractPath, request.getTaskId()));
components.addAll(visualforcePageParser.parse(extractPath, request.getTaskId()));
components.addAll(customObjectParser.parse(extractPath, request.getTaskId()));
components.addAll(customFieldParser.parse(extractPath, request.getTaskId()));
componentIndexMapper.insertBatch(components);
ComponentIndexResponse response = new ComponentIndexResponse();
response.setTaskId(request.getTaskId());
response.setTotal(components.size());
response.setMessage("Index created successfully");
return response;
}
}
遇到的问题: 无
解决方案: 无
4. 创建 IMetadataComponentQueryService 服务接口
执行内容: 创建 IMetadataComponentQueryService 服务接口,定义组件查询服务接口方法。
关键代码:
public interface IMetadataComponentQueryService {
ComponentQueryResponse queryComponents(ComponentQueryRequest request);
}
遇到的问题: 无
解决方案: 无
5. 创建 MetadataComponentQueryServiceImpl 服务实现
执行内容: 创建 MetadataComponentQueryServiceImpl 服务实现,实现组件查询服务接口方法,使用 MyBatis Plus 的 QueryWrapper 实现多条件查询。
关键代码:
@Service
public class MetadataComponentQueryServiceImpl implements IMetadataComponentQueryService {
@Autowired
private MetadataComponentIndexMapper componentIndexMapper;
@Override
public ComponentQueryResponse queryComponents(ComponentQueryRequest request) {
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
if (request.getType() != null && !request.getType().isEmpty()) {
queryWrapper.eq("component_type", request.getType());
}
if (request.getName() != null && !request.getName().isEmpty()) {
queryWrapper.like("component_name", request.getName());
}
if (request.getVersion() != null && !request.getVersion().isEmpty()) {
queryWrapper.eq("component_version", request.getVersion());
}
queryWrapper.orderByDesc("create_time");
Page<MetadataComponentIndex> pageResult = componentIndexMapper.selectPage(
new Page<>(request.getPage(), request.getSize()), queryWrapper);
ComponentQueryResponse response = new ComponentQueryResponse();
response.setTotal(pageResult.getTotal());
response.setPage(request.getPage());
response.setSize(request.getSize());
response.setRecords(pageResult.getRecords());
return response;
}
}
遇到的问题: 无
解决方案: 无
6. 创建 IMetadataComponentDetailService 服务接口
执行内容: 创建 IMetadataComponentDetailService 服务接口,定义组件详情服务接口方法。
关键代码:
public interface IMetadataComponentDetailService {
ComponentDetailResponse getComponentDetail(Long id);
String getComponentContent(Long id);
ComponentDetailResponse getComponentDependencies(Long id);
}
遇到的问题: 无
解决方案: 无
7. 创建 MetadataComponentDetailServiceImpl 服务实现
执行内容: 创建 MetadataComponentDetailServiceImpl 服务实现,实现组件详情服务接口方法,使用文件读取 API 读取组件文件内容。
关键代码:
@Service
public class MetadataComponentDetailServiceImpl implements IMetadataComponentDetailService {
@Autowired
private MetadataComponentIndexMapper componentIndexMapper;
@Autowired
private IFileStorageService fileStorageService;
@Override
public ComponentDetailResponse getComponentDetail(Long id) {
MetadataComponentIndex component = componentIndexMapper.selectById(id);
if (component == null) {
throw new RuntimeException("Component not found");
}
ComponentDetailResponse response = new ComponentDetailResponse();
response.setId(component.getId());
response.setTaskId(component.getTaskId());
response.setComponentType(component.getComponentType());
response.setComponentName(component.getComponentName());
response.setComponentVersion(component.getComponentVersion());
response.setFilePath(component.getFilePath());
response.setCreateTime(component.getCreateTime());
return response;
}
@Override
public String getComponentContent(Long id) {
MetadataComponentIndex component = componentIndexMapper.selectById(id);
if (component == null) {
throw new RuntimeException("Component not found");
}
File file = new File(component.getFilePath());
try {
return new String(Files.readAllBytes(Paths.get(file.toURI())));
} catch (Exception e) {
throw new RuntimeException("Failed to read component content", e);
}
}
@Override
public ComponentDetailResponse getComponentDependencies(Long id) {
MetadataComponentIndex component = componentIndexMapper.selectById(id);
if (component == null) {
throw new RuntimeException("Component not found");
}
ComponentDetailResponse response = new ComponentDetailResponse();
response.setId(component.getId());
response.setComponentName(component.getComponentName());
response.setComponentType(component.getComponentType());
return response;
}
}
遇到的问题: 无
解决方案: 无
8. 创建 IMetadataComponentStatisticsService 服务接口
执行内容: 创建 IMetadataComponentStatisticsService 服务接口,定义组件统计服务接口方法。
关键代码:
public interface IMetadataComponentStatisticsService {
ComponentStatisticsResponse getStatistics(String type, String version, Long orgConfigId);
ComponentTypeDistributionResponse getTypeDistribution(Long orgConfigId);
ComponentVersionDistributionResponse getVersionDistribution(Long orgConfigId);
}
遇到的问题: 无
解决方案: 无
9. 创建 MetadataComponentStatisticsServiceImpl 服务实现
执行内容: 创建 MetadataComponentStatisticsServiceImpl 服务实现,实现组件统计服务接口方法,使用 MyBatis Plus 的聚合查询实现统计功能。
关键代码:
@Service
public class MetadataComponentStatisticsServiceImpl implements IMetadataComponentStatisticsService {
@Autowired
private MetadataComponentIndexMapper componentIndexMapper;
@Override
public ComponentStatisticsResponse getStatistics(String type, String version, Long orgConfigId) {
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
if (type != null && !type.isEmpty()) {
queryWrapper.eq("component_type", type);
}
if (version != null && !version.isEmpty()) {
queryWrapper.eq("component_version", version);
}
Long total = componentIndexMapper.selectCount(queryWrapper);
ComponentStatisticsResponse response = new ComponentStatisticsResponse();
response.setTotal(total);
return response;
}
@Override
public ComponentTypeDistributionResponse getTypeDistribution(Long orgConfigId) {
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
List<MetadataComponentIndex> components = componentIndexMapper.selectList(queryWrapper);
Map<String, Long> typeDistribution = components.stream()
.collect(Collectors.groupingBy(
MetadataComponentIndex::getComponentType,
Collectors.counting()
));
ComponentTypeDistributionResponse response = new ComponentTypeDistributionResponse();
response.setDistribution(typeDistribution);
return response;
}
@Override
public ComponentVersionDistributionResponse getVersionDistribution(Long orgConfigId) {
QueryWrapper<MetadataComponentIndex> queryWrapper = new QueryWrapper<>();
List<MetadataComponentIndex> components = componentIndexMapper.selectList(queryWrapper);
Map<String, Long> versionDistribution = components.stream()
.collect(Collectors.groupingBy(
MetadataComponentIndex::getComponentVersion,
Collectors.counting()
));
ComponentVersionDistributionResponse response = new ComponentVersionDistributionResponse();
response.setDistribution(versionDistribution);
return response;
}
}
遇到的问题: 无
解决方案: 无
10. 创建 MetadataComponentParser 接口和实现类
执行内容: 创建 MetadataComponentParser 接口和 ApexClassParser、VisualforcePageParser、CustomObjectParser、CustomFieldParser 实现类,解析不同类型的元数据文件。
关键代码:
public interface MetadataComponentParser {
List<MetadataComponentIndex> parse(File extractPath, Long taskId);
}
@Component
public class ApexClassParser implements MetadataComponentParser {
@Override
public List<MetadataComponentIndex> parse(File extractPath, Long taskId) {
List<MetadataComponentIndex> components = new ArrayList<>();
File apexClassesDir = new File(extractPath, "classes");
if (!apexClassesDir.exists()) {
return components;
}
File[] files = apexClassesDir.listFiles((dir, name) -> name.endsWith(".cls"));
if (files == null) {
return components;
}
for (File file : files) {
MetadataComponentIndex component = new MetadataComponentIndex();
component.setTaskId(taskId);
component.setComponentType("ApexClass");
component.setComponentName(file.getName().replace(".cls", ""));
component.setComponentVersion("1.0");
component.setFilePath(file.getAbsolutePath());
components.add(component);
}
return components;
}
}
遇到的问题: 无
解决方案: 无
11. 创建 MetadataComponentIndex 实体类和 Mapper
执行内容: 创建 MetadataComponentIndex 实体类和 MetadataComponentIndexMapper 接口,使用 MyBatis Plus 的 BaseMapper 实现数据库操作。
关键代码:
@Data
@TableName("datai_metadata_component_index")
public class MetadataComponentIndex {
@TableId(type = IdType.AUTO)
private Long id;
private Long taskId;
private String componentType;
private String componentName;
private String componentVersion;
private String filePath;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
@Mapper
public interface MetadataComponentIndexMapper extends BaseMapper<MetadataComponentIndex> {
}
遇到的问题: 无
解决方案: 无
12. 创建 DTO 类
执行内容: 创建 ComponentIndexRequest、ComponentIndexResponse、ComponentQueryRequest、ComponentQueryResponse、ComponentDetailResponse、ComponentStatisticsResponse、ComponentTypeDistributionResponse、ComponentVersionDistributionResponse 等 DTO 类。
关键代码:
@Data
public class ComponentIndexRequest {
private Long taskId;
}
@Data
public class ComponentIndexResponse {
private Long taskId;
private Long total;
private String message;
}
@Data
public class ComponentQueryRequest {
private String type;
private String name;
private String version;
private int page;
private int size;
}
@Data
public class ComponentQueryResponse {
private long total;
private int page;
private int size;
private List<Object> records;
}
@Data
public class ComponentDetailResponse {
private Long id;
private Long taskId;
private String componentType;
private String componentName;
private String componentVersion;
private String filePath;
private LocalDateTime createTime;
}
@Data
public class ComponentStatisticsResponse {
private Long total;
}
@Data
public class ComponentTypeDistributionResponse {
private Map<String, Long> distribution;
}
@Data
public class ComponentVersionDistributionResponse {
private Map<String, Long> distribution;
}
遇到的问题: 无
解决方案: 无
13. 创建 ComponentIndexException 异常类
执行内容: 创建 ComponentIndexException 异常类,处理组件索引相关的异常。
关键代码:
public class ComponentIndexException extends RuntimeException {
public ComponentIndexException(String message) {
super(message);
}
public ComponentIndexException(String message, Throwable cause) {
super(message, cause);
}
}
遇到的问题: 无
解决方案: 无
14. 复用现有的服务
执行内容: 复用现有的 IFileStorageService 服务,无需新增服务。
遇到的问题: 无
解决方案: 无
关键产出
记录本次会话的关键产出:
- 生成的代码文件:
- MetadataComponentIndexController.java - 元数据组件索引控制器
- IMetadataComponentIndexService.java - 元数据组件索引服务接口
- MetadataComponentIndexServiceImpl.java - 元数据组件索引服务实现
- IMetadataComponentQueryService.java - 元数据组件查询服务接口
- MetadataComponentQueryServiceImpl.java - 元数据组件查询服务实现
- IMetadataComponentDetailService.java - 元数据组件详情服务接口
- MetadataComponentDetailServiceImpl.java - 元数据组件详情服务实现
- IMetadataComponentStatisticsService.java - 元数据组件统计服务接口
- MetadataComponentStatisticsServiceImpl.java - 元数据组件统计服务实现
- MetadataComponentParser.java - 元数据组件解析器接口
- ApexClassParser.java - Apex Class 解析器
- VisualforcePageParser.java - Visualforce Page 解析器
- CustomObjectParser.java - Custom Object 解析器
- CustomFieldParser.java - Custom Field 解析器
- MetadataComponentIndex.java - 元数据组件索引实体类
- MetadataComponentIndexMapper.java - 元数据组件索引 Mapper 接口
- ComponentIndexRequest.java - 组件索引请求 DTO
- ComponentIndexResponse.java - 组件索引响应 DTO
- ComponentQueryRequest.java - 组件查询请求 DTO
- ComponentQueryResponse.java - 组件查询响应 DTO
- ComponentDetailResponse.java - 组件详情响应 DTO
- ComponentStatisticsResponse.java - 组件统计响应 DTO
- ComponentTypeDistributionResponse.java - 组件类型分布响应 DTO
- ComponentVersionDistributionResponse.java - 组件版本分布响应 DTO
- ComponentIndexException.java - 组件索引异常类
- 更新的文档:无
- 解决的问题:无
- 达成的共识:复用现有的 IFileStorageService 服务
质疑与替代方案
记录在执行过程中提出的质疑和考虑的替代方案:
-
质疑:是否需要使用搜索引擎实现组件查询?
- 替代方案:使用 Elasticsearch 或 Solr 实现组件查询
- 评估:MyBatis Plus 的查询性能已经能够满足需求,使用搜索引擎会增加不必要的复杂度
-
质疑:是否需要使用缓存提高查询性能?
- 替代方案:使用 Redis 或 Caffeine 缓存查询结果
- 评估:MyBatis Plus 的查询性能已经能够满足需求,使用缓存会增加不必要的复杂度
-
质疑:是否需要使用 NoSQL 数据库存储组件索引?
- 替代方案:使用 MongoDB 或 Elasticsearch 存储组件索引
- 评估:MyBatis Plus 的查询性能已经能够满足需求,使用 NoSQL 数据库会增加不必要的复杂度
结论
总结本次会话的结果,包括:
-
完成的工作:
- 创建了 MetadataComponentIndexController 控制器,提供 8 个 RESTful API 接口
- 创建了 IMetadataComponentIndexService 服务接口,定义组件索引服务接口方法
- 创建了 MetadataComponentIndexServiceImpl 服务实现,实现组件索引服务接口方法
- 创建了 IMetadataComponentQueryService 服务接口,定义组件查询服务接口方法
- 创建了 MetadataComponentQueryServiceImpl 服务实现,实现组件查询服务接口方法
- 创建了 IMetadataComponentDetailService 服务接口,定义组件详情服务接口方法
- 创建了 MetadataComponentDetailServiceImpl 服务实现,实现组件详情服务接口方法
- 创建了 IMetadataComponentStatisticsService 服务接口,定义组件统计服务接口方法
- 创建了 MetadataComponentStatisticsServiceImpl 服务实现,实现组件统计服务接口方法
- 创建了 MetadataComponentParser 接口和 ApexClassParser、VisualforcePageParser、CustomObjectParser、CustomFieldParser 实现类
- 创建了 MetadataComponentIndex 实体类和 MetadataComponentIndexMapper 接口
- 创建了 ComponentIndexRequest、ComponentIndexResponse、ComponentQueryRequest、ComponentQueryResponse、ComponentDetailResponse、ComponentStatisticsResponse、ComponentTypeDistributionResponse、ComponentVersionDistributionResponse 等 DTO 类
- 创建了 ComponentIndexException 异常类
- 复用了现有的 IFileStorageService 服务
-
达成的目标:
- 实现了组件索引创建功能,支持多种元数据类型解析
- 实现了组件查询功能,支持按类型、名称、版本等条件查询
- 实现了组件详情查看功能,支持查看组件文件内容和依赖关系
- 实现了组件统计功能,支持按类型、版本、组织等维度统计
-
后续的行动计划:
- 创建数据库表 datai_metadata_component_index
- 编写单元测试和集成测试
- 编写 API 文档和使用文档
-
需要跟进的事项:
- 更新 Canvas,添加元数据组件索引和查询相关的节点
- 更新 CHANGELOG.md,记录本次变更
- 创建复盘报告,总结本次迭代的经验和教训
Design Update
- 是否需要更新 Canvas? 是
- Authentication.canvas - 需要添加元数据组件索引和查询相关的节点
- 其他 Canvas 文件: 无
复现步骤
提供复现本次会话结果的具体步骤:
- 创建 MetadataComponentIndexController 控制器,提供 8 个 RESTful API 接口
- 创建 IMetadataComponentIndexService 服务接口,定义组件索引服务接口方法
- 创建 MetadataComponentIndexServiceImpl 服务实现,实现组件索引服务接口方法
- 创建 IMetadataComponentQueryService 服务接口,定义组件查询服务接口方法
- 创建 MetadataComponentQueryServiceImpl 服务实现,实现组件查询服务接口方法
- 创建 IMetadataComponentDetailService 服务接口,定义组件详情服务接口方法
- 创建 MetadataComponentDetailServiceImpl 服务实现,实现组件详情服务接口方法
- 创建 IMetadataComponentStatisticsService 服务接口,定义组件统计服务接口方法
- 创建 MetadataComponentStatisticsServiceImpl 服务实现,实现组件统计服务接口方法
- 创建 MetadataComponentParser 接口和 ApexClassParser、VisualforcePageParser、CustomObjectParser、CustomFieldParser 实现类
- 创建 MetadataComponentIndex 实体类和 MetadataComponentIndexMapper 接口
- 创建 ComponentIndexRequest、ComponentIndexResponse、ComponentQueryRequest、ComponentQueryResponse、ComponentDetailResponse、ComponentStatisticsResponse、ComponentTypeDistributionResponse、ComponentVersionDistributionResponse 等 DTO 类
- 创建 ComponentIndexException 异常类
- 创建数据库表 datai_metadata_component_index
- 编写单元测试和集成测试
- 编写 API 文档和使用文档
- 验证元数据组件索引和查询功能是否正常工作
验证方法:
- 调用 POST /metadata/component/index 接口,验证组件索引创建是否成功
- 调用 GET /metadata/component/query 接口,验证组件查询是否正常
- 调用 GET /metadata/component/detail/{id} 接口,验证组件详情查看是否正常
- 调用 GET /metadata/component/detail/{id}/content 接口,验证组件文件内容查看是否正常
- 调用 GET /metadata/component/detail/{id}/dependencies 接口,验证组件依赖关系查看是否正常
- 调用 GET /metadata/component/statistics 接口,验证组件统计是否正常
- 调用 GET /metadata/component/statistics/type-distribution 接口,验证组件类型分布统计是否正常
- 调用 GET /metadata/component/statistics/version-distribution 接口,验证组件版本分布统计是否正常