早上的崩溃
早上 10 点刚打开电脑,测试组的小林就在群里甩了一张截图:搜索框输入超过 50 个字符就会页面卡死。我的心瞬间凉了半截——这是 CloverTools v1.3.2 刚上线第三天,又出幺蛾子了。
打开 Chrome DevTools 一看,控制台报的是 Maximum call stack size exceeded,栈溢出。定位到 src/components/SearchBox.tsx 第 89 行,问题出在我写的那个「智能补全」函数 getSuggestions() 里面。写的时候图省事,用了递归匹配,结果遇到长字符串,正则回溯次数直接爆表。
硬着头皮排查
第一次修复:给正则加了 .{0,50} 的长度限制,commit a7f3c21。测试通过,上线,10 分钟后小林又截图——这回是英文搜索正常,中文搜索还是崩。
我整个人都不好了。坐下来冷静想了半小时,突然意识到问题不在正则本身,而是我在 debounce 函数里又套了一层递归。代码第 23-41 行的 QueryProcessor 类,process() 方法里调了 this.fetchResults(),fetchResults() 失败时又调用 this.process() 重试——一旦超时触发重试,长文本递归层数直接破百。
第三次才搞定
删掉重试逻辑,改成 Promise 的 retry 库,commit b9e2d54。这次测试了 200 条不同长度、不同语言的搜索词,全部通过。下午 2 点重新上线,到现在已经稳了 4 个小时。
教训
这次修 bug 花了将近 4 小时,核心问题其实是我三天前写 QueryProcessor 时偷懒——觉得「反正不会失败」就没加保护。结果线上真实流量一跑,长文本一多,递归直接把浏览器干趴了。
技术债这东西,迟早要还的。下周我打算把搜索模块的重试逻辑和长度校验全部加上单元测试,以后谁敢删就让他写测试补回来。