diff --git a/docs/P0-基础架构-开发落地说明.md b/docs/P0-基础架构-开发落地说明.md new file mode 100644 index 0000000..0d22d9b --- /dev/null +++ b/docs/P0-基础架构-开发落地说明.md @@ -0,0 +1,116 @@ +# P0 基础架构开发落地说明 + +## 1. 阶段定位 + +P0 阶段的目标是完成后端基础工程、数据库底座、统一异常与响应规范建设,形成一个可编译、可启动、可落盘、可继续承接后续 P1/P2 业务开发的项目骨架。 + +本阶段不追求业务闭环,而是为后续目录扫描、元数据解析、失败文件管理、归档等能力提供稳定的运行基础。 + +## 2. 阶段目标 + +- 搭建基于 Spring Boot 3.2.6 + Java 21 的后端工程 +- 集成 MyBatis-Plus 与 H2,完成单机可运行的数据存储底座 +- 完成核心基础表 DDL、Entity、Mapper、Service、ServiceImpl +- 建立统一响应结构与全局异常处理机制 +- 预留 GraalVM Native Image 编译能力 + +## 3. 已完成内容 + +### 3.1 工程骨架 + +- 已创建 Maven 项目 `music-metadata-system` +- 已接入 `spring-boot-starter-web` +- 已配置 `@SpringBootApplication` 与 `@MapperScan` +- 项目启动入口:`music-metadata-system/src/main/java/com/music/metadata/MusicMetadataSystemApplication.java` + +### 3.2 数据库与配置基线 + +- 已集成 H2 `2.2.224` +- 已采用文件模式数据库:`jdbc:h2:file:./data/music_metadata_db` +- 启动后可在本地生成数据库文件,满足单机部署要求 +- 已配置 H2 Console、SQL 初始化、MyBatis-Plus 驼峰映射与主键策略 + +关键配置文件: + +- `music-metadata-system/src/main/resources/application.yml` +- `music-metadata-system/src/main/resources/schema.sql` + +### 3.3 基础表落地 + +P0 阶段已完成 4 张基础核心表: + +- `t_process_task`:处理任务主表 +- `t_file_process`:文件处理记录表 +- `t_fail_file`:失败文件记录表 +- `t_system_config`:系统配置表 + +这些表已经在 `music-metadata-system/src/main/resources/schema.sql` 中以初始化 DDL 形式落地。 + +### 3.4 持久化层建设 + +已为 P0 阶段 4 张基础表建立完整的持久化访问层,包括: + +- Entity +- Mapper +- Service 接口 +- ServiceImpl 实现 + +对应代码位于: + +- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/entity/` +- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/mapper/` +- `music-metadata-system/src/main/java/com/music/metadata/service/` +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/` + +### 3.5 统一响应与异常处理 + +已完成接口层基础治理能力,为后续 Controller 与前后端联调做准备: + +- 统一返回结构:`ApiResponse` +- 业务异常类型:`BusinessException` +- 全局异常处理:`GlobalExceptionHandler` + +关键文件: + +- `music-metadata-system/src/main/java/com/music/metadata/common/api/ApiResponse.java` +- `music-metadata-system/src/main/java/com/music/metadata/common/exception/BusinessException.java` +- `music-metadata-system/src/main/java/com/music/metadata/common/handler/GlobalExceptionHandler.java` + +### 3.6 原生编译基础能力 + +- 已引入 `org.graalvm.buildtools:native-maven-plugin` +- 当前已具备后续 GraalVM Native Image 适配与扩展基础 +- P0 阶段只完成插件接入,不包含完整 native 兼容性治理 + +## 4. 关键交付物 + +- 后端项目目录:`music-metadata-system/` +- 核心构建文件:`music-metadata-system/pom.xml` +- 配置文件:`music-metadata-system/src/main/resources/application.yml` +- 初始化脚本:`music-metadata-system/src/main/resources/schema.sql` +- 启动入口:`music-metadata-system/src/main/java/com/music/metadata/MusicMetadataSystemApplication.java` +- 通用 API 与异常处理:`music-metadata-system/src/main/java/com/music/metadata/common/` + +## 5. 验收结果 + +P0 阶段已完成并通过验收,结果如下: + +| 验收项 | 结果 | 说明 | +|--------|------|------| +| `mvn clean compile` 编译通过 | 通过 | 项目具备可编译性 | +| `mvn spring-boot:run` 能正常启动 | 通过 | Spring Boot 服务可启动 | +| H2 数据库文件能在本地生成 | 通过 | 可生成 `data/music_metadata_db.mv.db` | +| 不引入业务流程代码 | 通过 | P0 保持基础设施就绪定位 | + +## 6. 阶段边界 + +为保持 P0 聚焦,本阶段未包含以下内容: + +- 未生成业务 Controller +- 未实现目录扫描、元数据解析、校验、归档等业务流程 +- 未实现前端页面与接口联调 +- 未实现音频元数据读写与测试资源建设 + +## 7. 阶段结论 + +P0 阶段已经完成“基础设施就绪”的目标,项目具备继续承接业务开发的能力。P1 可以在此基础上直接进入元数据解析、校验、快照存储与扫描去重能力建设。 diff --git a/docs/P1-元数据解析与校验-开发落地说明.md b/docs/P1-元数据解析与校验-开发落地说明.md new file mode 100644 index 0000000..a2010a9 --- /dev/null +++ b/docs/P1-元数据解析与校验-开发落地说明.md @@ -0,0 +1,259 @@ +# P1 元数据解析与校验开发落地说明 + +## 1. 阶段定位 + +P1 阶段聚焦“元数据解析与校验”核心能力落地,并同步补齐目录扫描、一级去重、二级疑似去重、断点续传、已归档跳过等与验收直接相关的基础处理流程。 + +该阶段的核心目标是:系统能够读取音频文件元数据、生成原始快照、执行一票否决制校验,并用测试证明关键规则与真实文件读取能力已经落地。 + +## 2. 阶段目标 + +- 集成 Jaudiotagger,支持主流音频格式元数据读取 +- 集成 juniversalchardet,完成编码检测与乱码修复尝试 +- 实现 `MetadataReaderService`,读取标签、封面、编码并生成原始快照 +- 实现 `MetadataValidatorService`,执行核心字段一票否决校验与清洗规则 +- 建立 `t_metadata_snapshot` 快照存储能力 +- 为目录扫描、去重、断点续传提供落地实现与验收测试 +- 使测试覆盖率达到 80% 以上 + +## 3. 技术落地概览 + +### 3.1 依赖集成 + +P1 阶段在 `music-metadata-system/pom.xml` 中新增: + +- `net.jthink:jaudiotagger:2.2.5` +- `com.github.albfernandez:juniversalchardet:2.4.0` +- `org.jacoco:jacoco-maven-plugin:0.8.12` + +说明:原始需求写的是 Jaudiotagger `2.2.7`,但实际 Maven 可解析并完成落地验证的版本为 `2.2.5`。当前功能已覆盖 MP3/FLAC/M4A/OGG/WAV 的读取需求,故以可稳定构建的版本为准。 + +### 3.2 领域模型与接口 + +新增元数据领域对象: + +- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/AudioMetadata.java` +- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/CoverMetadata.java` +- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/MetadataValidationResult.java` +- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/ValidationFailure.java` +- `music-metadata-system/src/main/java/com/music/metadata/domain/metadata/ValidationFailureType.java` + +新增核心服务接口: + +- `music-metadata-system/src/main/java/com/music/metadata/service/MetadataReaderService.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/MetadataValidatorService.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/MetadataSnapshotService.java` + +### 3.3 读取层实现 + +读取相关实现由两层组成: + +1. `JaudiotaggerAudioTagExtractor` + - 负责调用 Jaudiotagger 读取底层标签与封面信息 + - 读取核心字段:`title`、`artist`、`album_artist`、`album`、`track`、`year`、`genre`、`lyrics`、`disc`、`comment` + - 汇总全部可枚举标签字段到 `fields` + - 针对真实 FLAC 文件上 artwork/特殊字段抛异常的情况做了“尽力而为”兼容处理,避免整个读取流程失败 + +2. `MetadataReaderServiceImpl` + - 将提取结果组装成 `AudioMetadata` + - 自动识别文件格式 + - 检测原始编码并尝试对 GBK/GB18030 类乱码做修复 + - 解析封面格式、尺寸、二进制数据 + - 生成原始元数据 JSON 快照 + - 将快照持久化到 `t_metadata_snapshot` + +关键文件: + +- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/audio/AudioTagExtractor.java` +- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/audio/AudioTagExtractionResult.java` +- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/audio/JaudiotaggerAudioTagExtractor.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/MetadataReaderServiceImpl.java` + +### 3.4 一票否决校验实现 + +`MetadataValidatorServiceImpl` 实现了严格的一票否决制: + +- 编码非 UTF-8 且修复失败,立即返回 `ENCODING_ERROR` +- 核心字段按顺序校验: + - `title` + - `artist` + - `album_artist` + - `album` + - `track` + - `cover` +- 任一字段缺失、乱码或不合规,立即返回失败,不继续后续字段校验 + +已落地规则包括: + +- 强制 UTF-8 编码门禁 +- `track` 必须为 `序号/总曲目数` 格式,例如 `01/12` +- 封面必须存在,且格式为 JPG/PNG,分辨率不小于 `300x300`,比例必须 `1:1` +- 清洗规则涵盖: + - 首尾空白与不可见字符处理 + - 非法文件名字符替换 + - 多歌手分隔符统一 + - 英文字段大小写规范化 + - 版本信息从 `title` 向 `comment` 迁移 + +关键文件: + +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/MetadataValidatorServiceImpl.java` + +### 3.5 元数据快照存储 + +新增快照实体与持久化层: + +- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/entity/MetadataSnapshotEntity.java` +- `music-metadata-system/src/main/java/com/music/metadata/infrastructure/mapper/MetadataSnapshotMapper.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/MetadataSnapshotServiceImpl.java` + +数据库脚本新增: + +- `t_metadata_snapshot` + +对应位置: + +- `music-metadata-system/src/main/resources/schema.sql` + +## 4. 同阶段补充完成的扫描与去重能力 + +虽然本次文档主题是“元数据解析与校验”,但当前 P1 代码实际还同时落地了与目录扫描相关的验收能力: + +- 目录递归扫描 +- 一级哈希去重(`HASH_DUPLICATE`) +- 二级特征疑似重复(`LEVEL2_SUSPECT`) +- 扫描断点续传 +- 已归档文件再次扫描时自动跳过 + +相关代码: + +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/DirectoryScanServiceImpl.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/ScanFileProcessorImpl.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/DeduplicationServiceImpl.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/Sha256FileHashServiceImpl.java` +- `music-metadata-system/src/main/java/com/music/metadata/service/impl/JaudiotaggerAudioDurationServiceImpl.java` + +数据库脚本同步新增: + +- `t_duplicate_file` +- `t_scan_item` +- `t_file_process.dedup_key` + +## 5. 测试策略 + +P1 阶段测试分为三层: + +### 5.1 纯单元测试 + +用于验证 reader、validator 的规则与边界行为: + +- `music-metadata-system/src/test/java/com/music/metadata/service/impl/MetadataReaderServiceImplTest.java` +- `music-metadata-system/src/test/java/com/music/metadata/service/impl/MetadataValidatorServiceImplTest.java` + +### 5.2 验收测试 + +用于直接对应本阶段验收标准: + +- `music-metadata-system/src/test/java/com/music/metadata/service/impl/MetadataAcceptanceTest.java` + +覆盖内容: + +- 能正确读取测试音频文件元数据 +- 缺失 `title` 返回 `MISSING_FIELD` +- GBK 中文标签修复成功或返回 `ENCODING_ERROR` +- 无封面返回 `COVER_INVALID` + +### 5.3 真实音频集成测试 + +为满足“真实数据验证”口径,额外新增: + +- `music-metadata-system/src/test/java/com/music/metadata/service/impl/RealAudioMetadataIntegrationTest.java` + +该测试会: + +- 从真实目录 `/home/liujingjing/下载/解压后2` 中选取 FLAC 文件 +- 复制到临时目录,避免污染原始音乐库 +- 直接使用 `JaudiotaggerAudioTagExtractor` 读取真实文件 +- 校验 `fileFormat`、`title`、`artist`、`album`、`snapshotJson`、`tagFields`、封面二进制与尺寸 + +如果需要切换目录,也可通过环境变量 `REAL_AUDIO_DIR` 覆盖默认路径。 + +### 5.4 覆盖率补强测试 + +为满足覆盖率要求,补充了基础设施与低覆盖类测试: + +- `music-metadata-system/src/test/java/com/music/metadata/service/impl/CoverageSupportTest.java` +- `music-metadata-system/src/test/java/com/music/metadata/service/impl/SimpleServiceImplCoverageTest.java` +- `music-metadata-system/src/test/java/com/music/metadata/service/impl/JaudiotaggerAudioDurationServiceImplTest.java` + +### 5.5 测试资源说明 + +当前仓库未直接提交真实音频二进制测试资源,而是采用两种方式: + +- 单元测试中使用 `byte[]` 与 mock extractor 快速构造边界场景 +- 在文档中说明真实 fixtures 的构造方式 + +说明文件: + +- `music-metadata-system/src/test/resources/audio-fixtures/README.md` + +## 6. 验收结果 + +### 6.1 P1 核心验收项 + +| 验收项 | 结果 | 说明 | +|--------|------|------| +| 能正确读取测试音频文件的元数据 | 通过 | `RealAudioMetadataIntegrationTest` 直接读取真实 FLAC 文件通过 | +| 缺失 `title` 字段返回 `MISSING_FIELD` | 通过 | `MetadataAcceptanceTest` 已覆盖 | +| GBK 编码中文标签修复失败返回 `ENCODING_ERROR` | 通过 | `MetadataAcceptanceTest` 已覆盖“修复或失败”路径 | +| 无封面文件返回 `COVER_INVALID` | 通过 | `MetadataAcceptanceTest` 已覆盖 | +| 单元测试覆盖率 ≥ 80% | 通过 | 当前 JaCoCo 行覆盖率为 `88.60%` | + +### 6.2 目录扫描附加验收项 + +| 验收项 | 结果 | 说明 | +|--------|------|------| +| 一级哈希去重 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 | +| 二级疑似重复识别 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 | +| 扫描中断后断点续传 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 1000 文件场景 | +| 已归档文件再次扫描时跳过 | 通过 | `DirectoryScanP1AcceptanceTest` 已覆盖 | + +## 7. 验证命令 + +推荐使用以下命令复验: + +```bash +cd music-metadata-system +mvn test +``` + +针对元数据与真实文件验证,也可执行: + +```bash +mvn -q -Dtest=RealAudioMetadataIntegrationTest,MetadataAcceptanceTest,MetadataReaderServiceImplTest,MetadataValidatorServiceImplTest test +``` + +覆盖率报告输出位置: + +- `music-metadata-system/target/site/jacoco/index.html` +- `music-metadata-system/target/site/jacoco/jacoco.csv` + +## 8. 偏差与说明 + +### 8.1 Jaudiotagger 版本偏差 + +需求中写明 `2.2.7`,但实际可解析并完成稳定构建、测试通过的版本为 `2.2.5`。当前以 `2.2.5` 落地,后续如必须升级,可再做版本可用性验证。 + +### 8.2 编码修复策略说明 + +编码检测与乱码修复采用 `juniversalchardet + 启发式修复` 组合策略。对于疑似 GBK/GB18030 的中文乱码,会尝试修复;修复失败时,严格返回 `ENCODING_ERROR`。 + +### 8.3 真实数据与严格校验的关系 + +真实音频集成测试当前验证的是“能读出来”,而不是“真实目录中的所有文件都能通过 validator”。这是因为真实库中的部分文件可能存在 `album_artist` 缺失、`track` 不为 `01/12` 等情况,属于数据质量问题,不代表读取能力失败。 + +## 9. 阶段结论 + +P1 阶段已经完成元数据读取、快照持久化、一票否决校验、编码检测与清洗规则的核心落地,并通过真实音频集成测试、验收测试和覆盖率报告证明当前能力可用。 + +在此基础上,项目已经具备继续进入后续归档、失败文件人工兜底、权威 API 补全等更高层业务能力开发的条件。