Skip to content

修复 1.6.0 代码审查发现的 25 项问题(下载台账并发 / 频道开关 / 目录误报 / 工程) - #19

Merged
Pau1am merged 1 commit into
mainfrom
fix/v1.6.1-audit
Oct 14, 2026
Merged

Pau1am merged 1 commit into
mainfrom
fix/v1.6.1-audit

Conversation

@Pau1am

@Pau1am Pau1am commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

改了什么

修复 v1.6.0 全代码审查(报告:工作区 ServerLogFilter-v1.4.1+ModUpdateChecker-v1.6.0-优化建议.html,原始报告 review-batch2/reports/A2、A3、A4)里 ModUpdateChecker 的 25 条发现(4×P1 / 12×P2 / 9×P3 + 优化项),并把仓库级工程项一并补齐。目标版本 v1.6.1。

台账与下载

  • 并发下载不再丢台账(MUC-01,P1):以前多个实例各自把内存快照整份写回,!!muc download 的两个后台线程、命令线程上的 install 与检查线程会互相覆盖(实测 9 条记录被清成 0 条),后果是「关服自动安装已批准的版本」静默失效。现在写入是进程级加锁的重读-合并-写回,JSON 临时文件名带上进程与线程号。
  • 下载失败不再先删旧版本(MUC-05,P2);安装失败不再在 mods/ 留下半截新 jar,改成同目录临时文件 + 原子替换,残留会点名(MUC-10,P2);台账里的文件名做安全校验、.. 不再被接受(MUC-18,P3);下载也计入限速、失败文案不再谎报重试次数(MUC-21/29)。

上游与检查

  • check.include_beta / include_alpha 之前完全不起作用(MUC-02,P1):频道过滤函数没有任何调用者,默认配置下 beta 会被当成可用更新推荐。现在生效;某个项目在所选频道没有版本时回落到更旧的频道并在报告里说明。
  • 关掉 sources.modrinth 不再污染解析缓存(MUC-04,P1):以前「没问过」被写成「确认不存在」,重新打开后这些 jar 在 24 小时内一次名字搜索都不会发。
  • 上游整体不可用时不再对每个 Mod 逐个搜索(MUC-12,P2;以前 12 个 Mod 会发 48 次搜索请求);close() 之后不再发请求(MUC-11);每线程一个 requests Session(MUC-22);超时拆成 connect/read 并给下载算总时长上限(MUC-27);JSON 响应加上限(MUC-28)。

健壮性

  • project-map.json 存成 GBK / ANSI 不再让整次检查失败(MUC-03,P1):以前 UnicodeDecodeError 会让 !!muc status 整页报错、检查以「check failed」收场。
  • 游戏版本投票只取下界、平局用真实版本比较(MUC-06,P2):以前给区间上界计票,猜错版本会让每个 Mod 显示「无适配构建」。
  • mods/ 读不到时不再报成「0 个 jar」:状态页写明原因,检查直接跳过(MUC-07 + 入口层接线)。
  • 其余:坏缓存记录不再让每次检查失败(MUC-09);scan_mods / classify_downloaded 的异常收紧(MUC-07/08);备份名判定改 fullmatch(MUC-17);加密或损坏的 jar 不再打破 scan_jar 的「不抛异常」承诺(MUC-19);元数据解压加 4 MiB 上限(MUC-20)。

入口层

  • !!muc status 改成两段式(MUC-15,P2):命令线程先回一句「正在读取」,扫描与渲染在后台线程完成后整屏给出——不再占用 MCDR 唯一的同步执行器线程;同一时间只允许一份状态页在生成。
  • 三处静默 except 补日志,_server_running 失败时沿用上次已知状态(MUC-13,P2):以前探测异常会静默丢弃所有玩家通知。
  • 暂存动作改原子取用、单条下载按文件名去重(MUC-14,P2);停服后在途检查丢结果(MUC-16,P2),并补上「停服→再开服不 reload」时定时检查的恢复。
  • 数值选项超出范围会被钳制并在控制台提示(MUC-26);列宽缓存在 reload 时失效(MUC-24);过宽的收尾行标题改为截断(MUC-25);!!muc 别名下不再写死 !!modupdate(MUC-23)。

工程与工具

  • 新增 tools/mutation_check.py:把每条守卫逐个改坏(在仓库的临时副本里改,工作树不受影响),对应的用例必须失败;「没被抓住」与「锚点挪走」分开报告——这取代了 CHANGELOG 里「27 处注入验证」那种不可复现的说法,并修掉 tests/test_docs.py 指向两个从未进过仓库的脚本的悬空引用。
  • 新增 tools/check_python_floor.py 与 CI 的 python-floor 作业:每个文件都必须能以 3.8 解析、且不用更新的注解写法或标准库名字(ruff.toml 的 target-version 只是配置,这一条才是检查)。
  • bench/ 的 7 个测量脚本连同 bench/README.md 进仓库,并新增 tests/test_documented_paths.py:文档里写出的仓库路径必须存在(此前 README-dev.md 引用了 7 个从未提交过的脚本)。
  • CI 新增 lint / python-floor / mutation 作业,两个 workflow 补 permissions / timeout-minutes / concurrency;打包器包内 changelog 只留最新一节(已发布的 v1.6.0 里那份是 28,363 B、占产物 29.4%,且与自身页眉矛盾)。
  • tests/test_docs.py 的 SECTIONS 补上 cleanup(此前整个 cleanup.* 命名空间不被校验;补上之后当场抓到 README-dev.md 把函数名写成了配置路径的样子)。

如何验证

项目 结果
pytest(含 2 项真实 MCDR 端到端) 827 passed(147 s)
python tools/mutation_check.py caught 12/12,exit 0
tools/mcdr_matrix.py(2.13.0 / 2.14.1 / 2.15.0 / 2.15.7 / 2.16.0) 五版本 PASS,跨版本断言逐项一致
python tools/check_artifact.py 可复现、CRLF 归一、包内 changelog 只留 v1.6.1 且与元数据一致
ruff check . = 0 项;tools/check_python_floor.py 51 个文件全部通过
台账并发自证 修复前「预期 9 / 实际 2」→ 修复后「预期 9 / 实际 9」
产物 ModUpdateChecker-v1.6.1.mcdr 91,947 B,sha256 24f2f11e…(与自检一致)

未跑:CI 本身(推送后由 GitHub 跑)。lint / python-floor / mutation 三个作业是新加的,若变红请把日志贴给我。

其它

  • 版本号 1.6.0 → 1.6.1;CHANGELOG.md 换成 v1.6.1 一节;README 的配置表补上每个数值选项的钳制范围,以及「mods 目录读不到会说明原因」的注意事项。
  • MUC-28 是部分修:HTTP 层加了 Content-Length 预检与累计上限,但 project_versions 的默认过滤没有加——那会抹掉「无适配构建」与「没有适配当前游戏版本的构建」两种判定的区别,取舍写在 review-batch2/fixes/MUC-core-fixes.md §⑥。
  • 一处曾报 P3 的「README-dev 有 6 个一级标题」经复核是误报:那几行是 ```bash 代码块里的 shell 注释,围栏感知的标题扫描显示每个文档都只有一个 H1,因此没有改动。

Ledger and downloads (MUC-01, 05, 10, 18, 21, 29): the download ledger is
written under a process-wide lock that re-reads and merges, so concurrent
download threads, the install command and the check thread no longer overwrite
each other's records (9 records reproduced losing to 0); an older download is
removed only after the new file is in place; a failed install no longer leaves
a truncated jar in mods/ and names the leftover when it cannot clean up; ledger
file names are validated before use; the failure message reports the attempts
that were actually made; downloads count against the rate limiter.

Upstream and checking (MUC-02, 04, 11, 12, 22, 27, 28, 30): release channels
are filtered for real (the switch previously had no caller, so beta builds were
offered as updates); a negative identification is only cached when Modrinth was
actually asked; advisories move inside the try so no request outlives the
client; a dead upstream short-circuits instead of searching once per mod;
each thread gets its own requests Session; timeouts become (connect, read) with
a total deadline for downloads; JSON responses gain a size cap; the wasted
per-mod version lookups and the dead assignment are gone.

Robustness (MUC-03, 06, 07, 08, 09, 17, 19, 20): a project map saved as
GBK/ANSI is reported and ignored instead of taking the whole check down; the MC
version vote only counts lower bounds and breaks ties with the real version
comparison; an unlistable mods/ returns an explained result rather than an
exception; hash reads go through one guarded helper; a malformed cache record
is dropped instead of failing every check; backup names are matched with
fullmatch; encrypted or corrupt jars no longer break scan_jar's "never raises"
promise; metadata extraction has a 4 MiB ceiling.

Entry layer (MUC-13, 14, 15, 16, 23, 24, 25, 26, 31): the three silent excepts
log; a failed is_server_running probe keeps the last known state instead of
muting every notification; taking a staged plan is atomic and single downloads
are de-duplicated by file name; a check that is still running when the server
stops drops its result; !muc status reads and renders off the command thread;
the alias reaches every line that names a command; the cell-width cache is
dropped on reload; an over-wide caption is cut to the title bar; numeric config
values are clamped to documented ranges with a warning; the module documents
its own section order and split plan.

Repository and tooling: tools/mutation_check.py replaces the hand-run injection
checks (12 mutations, temporary copy, stale anchors reported separately),
tools/check_python_floor.py plus a CI job verify the declared 3.8 floor, the
bench scripts README-dev cites are in the repository with a path guard test,
the packaged changelog is trimmed to one section, and the workflow gains
permissions, timeouts, concurrency and a lint job.

Verified: 827 tests pass; 12/12 mutations caught; the real MCDR matrix agrees on
2.13.0 / 2.14.1 / 2.15.0 / 2.15.7 / 2.16.0; the artifact is reproducible.
@Pau1am
Pau1am merged commit 0d43c10 into main Oct 14, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant