# 英语词典变更与QA影响分析 · 2026-11-04

当前不宜仅凭已有单元测试通过判定可验收。优先风险是音频补发布穿透人工草稿；其次是首次发布与异步计算竞态造成正式库持续缺分词行。问题依据是当前源码控制流与部分原方法隔离执行，未证明目标环境已经发生。

## 版本、范围与证据

课程中心后端 `feature/qiyangyang/597084`，固定 `0baa9ebe8b7f9ecc46f675acbf1f56ac65378957`（2026-11-04 13:57:43 +08:00）；系统基线远端master `873c4f2d7c63a947216ae92bdc393b73408b6b6e`（2026-11-02 19:59:22 +08:00，v3.11.2）；演进对照为本分支2026-10-30 12:34:54的 `e9f2fb1b58a2a0292e5a95a9cbeb6fae7f956682`。master树没有本英语分词新增模块；历史审核版本不能替代系统master。

本次需求是三份在线词库/短语库/同步发布分词文档，重新读取正文与14条评论，当前Spec2.1.9全文与适用子计划按专项读取。原始返回与版本、差异清单留在证据目录。分支相对历史的264文件变化包含合入master及知识材料等其他功能，不能把264文件全部当作本英语需求；仅沿英语调用、共享资源、缓存、MQ、数据源与实际读写关系追踪。未给出实际环境部署版、真实前端仓库和C端源码，页面入口只依据PRD“公共资源空间→英文词库→单词/短语Tab”，URL未取得。

在线需求本轮实际变化：短语查重已改为原形与变形全局联合唯一；分词明确同步、发布两时机；撇号与连字符不切（it's、low-temperature）。Spec关于PRD未要求联合查重的X5已经过时；算法7.3只写连字符也应补撇号。音频恢复人工必填，与10月30日临时可空裁决有实质变化。不能沿旧用例把这些变化误判回归。

## 改造前完整业务机制

master没有新英语词典/分词能力，现有题目同步、发布、资源表、通用缓存和MQ是复用底座。下述“改造前”专指已实现英语功能的10月30日历史版本。

运营在教研库新增/编辑词条，归一化查重，翻译或变体作为子集合写入；编辑回待发布、保留曾发布事实。音频audioUrl可省略并登记本地资源；导入与补录同步等待TTS生成、下载上传后建词，失败可缺音频。单条发布在实体/文本锁中重读，正式库事务映射主/子/资源ID并差集删除，提交后回写教研库状态并异步清缓存。发布之外的草稿不得改变正式库。

LABS同步事务提交后直接在回调计算：抽取富文本→短语最长优先→剩余单词→每内容位落text/type序列→登记未命中关系→投补录。该版填空当数组、输入读判定区是已确认历史错误。保存剪枝要求MD5和revision；题目发布可携带教研分词快照到正式库。每日和手动全量按JY后PROD重算，正式库完全缺行不自增；详情接口用phraseRefs选择原形或特定变形。短语索引本机失效，其他进程靠TTL。

## 改造后完整业务机制

1. **人工维护**：单词、短语原形和已添加变体均要求audioUrl；地址登记不看后缀，但保存末端资源存在/未删除/mp3-wav门仍有效。词条保存保持待发布语义；单词完整性改为合并已有实体再算。导入固定source2、补录source3，人工source1不参与自动提交音频。
2. **同步分词**：题目与表单提交后只投ID消息；worker显式切教研库、重读最新题和表单，强制比对短语版本后计算。不随消息携带旧正文，因此“旧消息”通常读最新题；但读题后并发更新仍依赖写侧revision门。对象作答正文与分类数组正确分支，禁止读判定答案。
3. **计算与写入**：按内容位分组、每文本块独立去HTML/公式/图片，归一化后短语最长优先、词集合去重批查；输出序列保留重复和顺序，未命中以负ID占位。库存只存text/type；同正文NORMAL可剪枝（当前不再要求相同revision）。每行revision条件写后删除不在本轮的旧类型，后一步没有题级revision门。unmatched表已删除，未命中只有内存集合和补录消息。
4. **题目发布**：当前代码实际上不搬教研segments；只有教研全部分词成功时，才为正式库缺失类型创建INIT空骨架，已有行不修改。之后发发布重算MQ，worker显式切正式库、强制校版本，再按正式题正文计算并允许MD5剪枝。INIT不下发。Spec6/9.4和Plan10仍写先搬序列再重算，与代码不同。
5. **全量与恢复**：每日/手动共用watchdog锁，JY后PROD串行，按题表ID游标分页，逐题force绕过正文剪枝，单题失败继续、末尾清孤儿；PROD完全缺行仍跳过。总开关和execution急停已分别接入；execution关时既有结果仍可下发。全量不投补录，丢投已明确接受无自动恢复，不能再承诺旧台账对账。
6. **音频状态**：导入/补录先建空音频词。十分钟后Job每表取batch候选提交TTS，记录taskId/taskTime；在途按提交时间和ID取前batch。running超时取消清任务；completed保留人工音频，否则下载上传登记并在音频仍空时条件回填。正式库不复制任务列。回填后hasPublished1调用完整发布，因此“曾发布”与“当前已发布版本”混用是本轮P1。
7. **读侧与RPC**：题目下发取所有未删分词行，任一非NORMAL/坏JSON整题null，成功按内容位升序并用当前词典补ID。只有短语块失配才局部重扫，不把库存两个word合并为新phrase。详情改为wordIds+phraseIds，总数1~100按原请求长度，单库env0/1；短语一条返回原形及全variants，C端按matches.variantId定位变形。旧phraseRefs已删除，旧客户端必须同步升级；混合旧请求可能仅返回words，不能以HTTP/RPC成功认为兼容。

## 缓存版本机制、正常与异常边界

当前全部落库外层入口都有forceVersionCheck：同步consumer教研、发布consumer正式、全量每库轮首。此前仅检索application会漏掉worker调用，本次已用全仓反证纠正，不把“没有强制调用”列为缺陷。

正常更新：提交后INCR版本→读侧发现版本不同→丢本机entry同步重装→新句柄。普通下发按默认30秒窗口节流，写入口force绕过窗口。真实Caffeine与当前完整索引隔离执行确认 NORMAL_FORCE version=1。

异常：新版本重装时DB失败，loadSnapshot返回lastKnown旧快照，force返回void、不向调用方报告版本追平失败；进入30秒退避，readySnapshot继续给旧句柄。原类探针输出 FAILED_FORCE returnsOld=true local=1 remote=2。这是Spec明示fail-open的容错取舍，但与“绝不用旧词典落库/窗口不影响数据正确性”的保证冲突：旧句柄仍可被计算写成NORMAL。建议测试明确“保可用”与“允许持久化旧块”的不同断言，若要禁止旧块持久化，必须给写入口可判定的新鲜度结果。未跑业务DB，该项列条件风险，未当作Redis故障必然的独立产品Bug。

UNKNOWN_VERSION时后续比对直接跳过，直至TTL刷新重新取得版本；版本键读不到/INCR失败也退TTL。正常情况下新增版本能缩短可见延迟，不意味着任何故障下都秒级。180分钟refreshAfterWrite、5分钟expireAfterAccess及全局Redis过期策略是不同层；持续热点不受“5分钟无人访问淘汰”约束。测试须记录具体键、环境及预热条件，不能泛称清缓存后立即生效。

## 分段对照与测试影响

| 业务对象 | 历史行为 | 当前行为 | 必测结果 |
|---|---|---|---|
| 作答区 | 错读数组/判定区 | 读实际正文对象或分类数组 | 四题型、真实Schema、答案词绝不混入序列 |
| 异步分词 | 提交后线程直接算 | MQ受理后worker算 | 停consumer、积压、投递失败时新正文与旧序列隔离 |
| 发布分词 | 搬成功快照 | 成功JY行驱动INIT骨架 | JY未算/FAILED/正常三状态，首次发布竞态与再次发布恢复 |
| 音频 | 调用线程等TTS | 空音频建词、Job提交回填 | 资源回填、人工并发、完整性、缓存、草稿不得自动发 |
| 短语详情 | refs选一个变形 | phraseIds带全部变形 | 老新客户端、变形定位、顺序、空数组和跨库ID |
| 索引 | TTL跨进程收敛 | 版本号+force校验 | 跨进程暖表、新版本DB失败/Redis失败、退避恢复 |
| 补录台账 | 持久关系存在但无恢复者 | 删除台账、承认无自动重投 | 不把每日刷/同MD5同步当补录恢复；明确人工处置 |
| 导入 | 重复跳过与同步音频 | 同样跳过、source修正、异步音频 | CSV坏引号/非法变形重导、limit0、数据计数与音频晚到 |

## 回归执行顺序及通过门槛

第一组优先：已发布无音频词→TTS在途→人工改翻译并上传音频仅保存→平台完成；对比JY草稿和PROD旧版本，正式库非音频字段不得被自动发布。原handleInFlight/queryInFlight隔离执行已确认该分支会调publish，但真实发布事务传播目前为源码证明。

第二组优先：首次同步后暂停compute消费→立即发题→恢复消费→再跑日刷。应验证学生库最终可用，当前缺骨架门可能使segments始终null。对照JY已成功再发布可恢复。已有题改正文时另验MQ窗口不下发旧序列，不与首次无行混成一例。

第三组：batch=1，两个待音频词。首ID连续提交失败3次后服务恢复，后ID应被提交；accepted后failed反复3次应停；completed下载持续失败/查询持续异常均超过1800秒应收口。三种根因分别断言，不用“最终没有音频”一个结果代替。

第四组：唯独缺音频的完整字段导入词回填后，JY和PROD的audioUrl、completeness/complete、暖缓存同时检查；缺翻译对照仍应不完整。再覆盖RPC1/100/101项、重复IDs、旧phraseRefs、新phraseIds、变体空集合/排序及环境隔离。

其余专项矩阵包含原型字段、富文本边界、撇号/数字/IPA、跨内容位乱序、分页、权限、开关、删除、导入格式及缓存失败。均为测试设计，未在业务环境执行。源码静态、原方法探针、真实业务验证分别记录，不用自动化测试类存在证明验收。

## 范围限制与交付判断

本轮重点新异步链路、实际变更与旧问题受影响路径；不声称旧22项所有缓存故障模式都完整重跑。旧作答区P1、导入来源、逆序锁、完整性稀疏更新已修；旧白名单按新必填/格式约束改变口径；旧孤儿unmatched风险随表删除失效。旧CSV、参数、POS、搜索、跨内容位问题仍有当前证据。原LocalRedis投毒、旧loader失效竞态尚需专项故障注入，不以未重跑销账。

缺少业务环境部署版本、真实MySQL/Redis/MQ/TTS/OSS、前端/C端联调、全量A1/A2文件执行与权限平台注册证据。受项目AI禁止Maven限制，本轮无全项目构建/JUnit执行。已完成本地原类/原方法javac：CSV与参数、新批量Job、分词tokenizer、短语索引及音频在途分支。探针外部依赖为替身，编译桩适配失败不作业务缺陷。
