# R01-D4-2 GET 评分快照停写实施报告 日期:2026-09-16 状态:实现与自动化复验通过,待独立真实环境黑盒验收。 ## 1. 变更结论 `CandidateScoringEngineService#getOverview`、`getDimensionDetail`、`getCompanyScoring` 已改为 `@Transactional(readOnly = true)`,并移除 `CandidateScoringCalculator#upsertSnapshots` 调用。 三个接口仍以同一次 `capturedNow` 实时计算并返回原响应结构,趋势接口继续读取已物化快照。 快照更新改由 D4-1 的写侧登记、后台 Worker 和补偿扫描负责。生产配置默认启用刷新与补偿; test、integration-test、mysql-it profile 显式关闭调度,仅由测试主动驱动,避免后台线程干扰断言。 ## 2. D4-1 网关补齐 V44 同时创建 `candidate_scoring_refresh_scan_checkpoints`。补偿扫描使用持久化游标、固定单轮预算和 `SELECT ... FOR UPDATE` 串行推进;游标与任务登记同事务提交。扫描到尾部后从 0 开始下一轮,避免首 页饥饿,也不会单次遍历全量用户。 真实 MySQL 8.4 Testcontainers 已验证:V1–V44 迁移和 schema validate、游标持久化、每轮预算、 Writer 幂等与强制版本、并发唯一领取、处理中重登记、租约恢复、失败事务隔离。 ## 3. 测试迁移 - `R01D4GetWritesSnapshotEvidenceTest` 改为逐字段快照,证明 overview、dimension、trend GET 零写入。 - `CandidateScoringEngineServiceTest` 与时钟一致性测试显式断言三个 GET 从不调用 upsert。 - `CandidateScoringPersistenceIntegrationTest` 显式调用 Calculator/Writer 验证物化幂等,不再借 GET 造数据。 - `V38AbilityRankingIntegrationTest` 显式走真实物化入口,原排名公式和结果断言保持不变。 首次干净全量构建据此发现 V38 排名测试仍依赖 GET 副作用(1 Error);修正夹具后专项测试通过, 再次执行干净全量构建成功。 ## 4. 实测结果 | 项目 | 结果 | | --- | --- | | D4-2 + D4-1 H2/MySQL 组合定向 | 38 / 38,0 failure,0 error,0 skip | | 时钟与持久化定向 | 13 / 13,0 failure,0 error,0 skip | | V38 排名回归 | 1 / 1,原断言不变 | | `mvn clean verify` | 2131 / 2131,Failures=0,Errors=0,Skipped=0,BUILD SUCCESS | | MySQL Testcontainers | Q01 与 V44 用例均真实执行,无跳过 | | OpenAPI | 176 paths / 214 operations,校验通过 | | `git diff --check` | 无空白错误,仅既有 LF/CRLF 提示 | ## 5. 边界 V44 是唯一新增迁移,V1–V43 未修改;无新增公网接口、ErrorCode、RabbitMQ 消息或通知;未暂存、 未提交、未推送;历史未跟踪文件未删除或移动。 ## 6. 待独立验收 仍需使用最新 JAR 与项目真实 MySQL/Docker 环境完成:三条真实 HTTP GET 前后快照逐字段零变化; 写侧事件到任务登记再到快照可见;趋势、申诉、排名、看板、公平性监控不退化;RabbitMQ 队列终态 为零;并精确清理或记录隔离验收数据。自动化与 Testcontainers 结果不能替代该黑盒步骤。 > R01-D4-2 实现及自动化复验完成,待独立真实 MySQL/Docker 黑盒验收。