← 返回博客2026-08-28

缓存文章的内容测试:回读 read_cache.rs 的 TTL、字段白名单和 p95 限定

AI 写出来的技术文章不能只靠 file:line 摆样子。我们把一篇缓存文章里的 TTL、字段白名单、失效路径和延迟限定写进 website test:源码一漂移,文章先红。

问题不是文章写得像不像

AI 写技术文章最安静的失败模式,是代码已经变了,文字还一脸笃定。file:line 引用能帮忙,但如果没人检查,它只是一个书签。下一次改动可能把 TTL 改掉、把返回字段放宽、把失效路径挪走,而公开文章仍然在讲旧事实。

这篇文章背后的 branch commit 是 ab6b277b6fb5fc4689826ee218a442c008678fc0,它被 bd78108af3ab1dc0a24f5c6e821afbc602a631d4 这个 merge(Merge feat/blog-fairness-fail-closed)合入。这个 branch 不只是发布了 read-cache contract 文章,也给这篇文章加了测试。

可复用的 lesson 不是“每一句文案都写测试”。真正值得抄的是:公开技术内容一旦承载信任、安全或产品承诺,就要在发布前把关键 claim 变成可执行检查。

先挑会伤信任的 claim

那篇缓存文章说了几件不能漂移的事:session 和 /api/auth/me cache 是 5 秒窗口,头像/昵称 cache 是 60 秒,缓存头像数据不能带 email,warm-path 的微秒预算不是生产延迟承诺。

第一层测试先把这些承诺列出来。在 commit ab6b277b6fb5fc4689826ee218a442c008678fc0 里,名为 pins the cache windows, invalidation boundary, field allowlist, and latency disclaimer 的测试读取 cache-the-read-path-contract 的中英文正文,确认文章仍然写着 TTL、no-email 边界、membership/entitlement 只依赖安全 TTL 的 caveat,以及延迟数字的限定范围。它还拒绝两个旧的错误说法,避免后来改文案时把 overclaim 又带回来。

但这还不够。只读文章自己的测试,最多证明文字没有自相矛盾;它不能证明文字还和代码一致。

让内容测试去读源码

真正有用的是 commit ab6b277b6fb5fc4689826ee218a442c008678fc0website/tests/posts.test.mjs 加的 sourceRange() helper。它会读取仓库文件,再切出文章引用的那段真实源码。后面名为 keeps the cited Rust source ranges aligned with the cache contract 的测试不信任文章正文,而是直接打开 Rust 源码,检查真实 token:SESSION_TTLME_TTLAVATAR_TTL、不含 emailCachedAvatar、generation 防 late insert、session invalidation、头像查询字段,以及 warm-path p95 断言。

这样文章就有了 fail-closed 路径。以后如果有人把 5 秒改成 30 秒、把 email 塞进头像缓存类型、删掉 generation guard,或者把 service-path 回归预算写成生产延迟承诺,website test 会先红,静态站不会被当成可发布状态。

它不能替代 reviewer

这套做法是 tripwire,不是 reviewer。它不能判断英文有没有力度、中文是不是自然、文章选题是不是最值得写,也不能覆盖所有可能的 claim。它同样不会把一个性能数字变成生产承诺;缓存文章仍然把 5,000 微秒写成进程内 service-path 预算,而不是线上主机指标。

重点是把两件事分开:cross-vendor review 继续审清晰度、框架和 overclaim;内容测试负责机器能检查的部分——源码范围、常量、字段边界,以及已经被 review 打掉、绝不能回来的说法。

我会复用的规则

以后让 AI 写公开工程内容,我会按这个清单处理:

  1. 挑出三到五个一旦漂移就会伤信任的 claim;
  2. 给每个 claim 放一个具体的 file:line 来源;
  3. 写内容测试去读那段源码,而不是只读文章文字;
  4. 连反面也一起测:不能出现的字段、review 已经删掉的说法、必须保留范围限定的延迟数字;
  5. 把素材 merge 写进 sourceShas[],避免 blog miner 下次换个标题又推荐同一件事。覆盖检查在 scripts/blog/blog-candidates.mjs:67-83

技术文章不应该等读者来抓错,才第一次享受“可执行证据”。如果这个 claim 重要,就在它上官网前先变成测试。