DEV LOG · v4.1.0

踩过的坑,比做成的功能更值得写下来。

这不是变更日志——功能清单在「建设现状」页。这里记的是过程中真正卡住过的地方: 现象是什么、根因在哪、最后怎么处置的。多数坑的共同点是它们都不显眼

建设脉络

踩过的坑

配置文件从来没被读过

现象
示例配置文件一直在,服务启动失败时还提示「请在 .env 中设置」。
原因
没有任何代码读取它。写进去的配置全部不生效,而错误提示反过来让人以为写了就有用。
处置
补上加载逻辑,规则是真实环境变量优先、配置文件只补空缺—— 否则线上用环境变量设的值会被仓库里的文件悄悄覆盖。

隧道地址拿到了,请求全部失败

现象
公网隧道建立成功、地址也拿到了,但所有请求返回 530
原因
出网环境封了 UDP 7844,而隧道客户端默认走 QUIC,握手一直超时。 它的启动预检其实已经打印了「UDP 不通、TCP 通」,只是淹没在日志里。
处置
强制走 HTTP/2 回退,立即注册成功。这条写进了部署文档—— 换台机器大概率还会遇到。

边缘防护悄悄吃掉埋点

现象
换到正式域名后,自检九条全部 403, 但用 curl 手工发同一个请求却是 200。
原因
CDN 的机器人防护按 User-Agent 拦截。实测 12 种主流 HTTP 客户端, 只有一种被拦——恰好是自检脚本用的那种。
处置
脚本改发具名 UA,并在全 403 时直接输出「这是边缘拦截」的判断。 真正危险的是:被边缘拦掉的请求根本到不了服务端, 兜底队列救不了、日志里也看不见——表现为「上游以为发了,我们这边什么都没有」, 正是数据不可追补的那种丢法。

图上的箭头全丢了,截图看不出来

现象
一张流程图渲染「正常」,截图检查也没发现问题。
原因
共享样式表里有一条针对图形元素的通用规则, CSS 会覆盖 SVG 的表现属性——箭头标记被换成了一个不存在的引用, 警示用的语义色也被刷成了普通灰。图的核心信息(哪两段还没通)视觉上完全消失。
处置
改用不设子元素样式的独立容器,并把验证方式从「看截图」换成 读取计算后样式逐项核对。后来画大幅架构图时, 又用脚本量了全部 68 个文字元素的包围盒做重叠检测——零碰撞。

差点为一个假想的消费者做抽象

现象
注意到姊妹项目与本项目「结构同构」,一度把「抽出共用模块」 列为当前最该做的技术投入。
原因
那句「结构同构」来自代码注释,没有人去量实际重叠。 实测后发现两边根本没有重复代码:一边 106 行含类型化契约与兜底队列, 另一边 33 行写自由字典;规则相关的代码,姊妹项目一行都还没写。
处置
否决自己的建议。为一个真实消费者加一个还没动工的假想消费者做抽象, 接口大概率要推翻重来。结论是「现在不做」,并把证据写下来。

规则通过了校验,却会破坏数据

现象
类型化提取的模型调用路径此前从未被真实验证过——测试里它是被替身覆盖的。 实测后发现:某条归一化规则通过了全部结构校验,参数键合法、正则能编译。
原因
它用了另一种语言的反向引用语法,在本运行时会被当成字面量插入—— 把「2023年」变成「$1年」。拿它自己的六条证据样本回算,0/6 成立。 结构合法不等于语义正确:schema 只能挡住形状不对的参数。 更危险的是这种规则会一路走到人工审核,而审核人看到「像模像样的正则」很可能就批了。
处置
用设计里已有的东西:规则强制附带的证据样本,就是它自己的测试用例。 入库前把规则应用到每条样本上回算。判据分三态——改对、没改(正则未匹配,原样返回,无害)、 改坏(一票否决)——再加覆盖率下限。 真实模型复测:三轮中一轮放行,改对 4、未覆盖 2、改坏 0。 未覆盖的样本会继续产生修正记录,攒够了自然提出配套规则,一次解决一部分

几条被反复验证的做法

测试先红后绿,而且要验证它真的会红

每个功能都先写会失败的测试。更进一步:写完防回归测试后, 把旧写法塞回去确认它确实变红——否则你可能只是加了一条永远为真的断言。

把约定变成会失败的测试

文档里写「改了要同步」,没人会记得。有一条测试盯着文档里写死的测试数量, 七次改动触发了七次拦截——包括一次跨分支合并时自动发现文档过期。 约定靠自觉会漂移,靠测试不会。

验证要量化,不要靠眼睛

截图「看着没问题」骗过一次之后,后续的图形验证全部改成读计算样式、 量包围盒、算重叠。同理,部署完不只看「进程在跑」—— 直接杀掉进程,确认它会自己回来,那才叫守护。

结构化的东西可以校验,自由文本不能

规则从自然语言改成带 schema 的参数之后,模型编造出一个不存在的数据源名, 入库时当场被拒。写文档时作者本人就编过一个这样的源名,是自查脚本抓出来的。 能被机器拒绝的错误,就不该留给人去发现。

← 回首页 · 建设现状