lmk123 / blog

个人技术博客,博文写在 Issues 里。
https://github.com/lmk123/blog/issues
623 stars 35 forks source link

两个 P0 事故的反思 #96

Open lmk123 opened 2 years ago

lmk123 commented 2 years ago

最近在开发划词翻译的时候,半个月内整出了两起 P0 事故:

感觉苗头不对,我准备自我反思一下。

先说说这俩 P0 出现的原因。

https://github.com/lmk123/crx-selection-translate/issues/1115 的原因是我在开发记住用户选择的双语 / 原文 / 译文选项的时候,在读取用户选择的选项时没有设置默认值,代码如下:

browser.storage.local.get('pageShowType').then(({ pageShowType }) => {
  setPageShowType(pageShowType)
  // ...
})

由于这是一个新增的选项,所以当用户更新到新版本之后,这里读取出来的 pageShowTypeundefined,导致了后面的报错。修复方法就是给它加了一个默认值,如果读取到 undefined 就设置为“双语”。

lmk123/crx-selection-translate#1125 的问题就出的更不应该了——我把 Firefox 的安装包发布到 Chrome 上去了。Chrome 使用了 webextension-polyfill,会增加一个 browser 全局变量,但是由于 Firefox 本身就有这个全局变量,所以没有加 webetension-polyfill,结果导致 Firefox 的安装包在 Chrome 里运行时抛出了“browser is not defined” 的错误。

这些错误回想起来都是很不应该出现的错误,稍微细心一点都不会犯,然而往往越是这些不起眼的地方,造成的伤害越大。为了以后不再出现类似的问题,我反思了以下几个方案。

进一步缩小灰度发布范围

随着划词翻译的代码库越来越庞大,我发布新版本的时候也越来越提心吊胆。还好 Chrome 支持灰度发布,可以在发布新版本时选择只让一定百分比的用户更新到新版本。

发布 lmk123/crx-selection-translate#1115 时就是分阶段发的,一开始只发了 10%,后面分为 4 天逐步增加到 80% 的时候,才有用户提出了这个反馈。但是,发布 lmk123/crx-selection-translate#1125 的时候我自认为改动很小不会出问题,所以一开始就发了 30%(本来写的是 50% 后来犹豫了一下才改成了 30%,现在回想起来真是救了我一命),也就是说估计有 8 万用户在发布的当天用不了划词翻译了。

……

所以,我决定以后每次发布新版本都先发个 5% 看看情况,后面再慢慢加。

使用离线安装包测试功能完整性

每次在发布之前,我只用本地的代码测了一下功能是否正常,这也导致了这两个问题没有被测出来:

所以,我决定:

  1. 在发布前用本地代码测试时,一定要移除本地扩展重新安装,确保 storage 里是空的再测试,避免出现 lmk123/crx-selection-translate#1115 的情况
  2. 代码提交审核并下载了离线安装包后,再用离线安装包测试一遍,避免出现 lmk123/crx-selection-translate#1125 的情况

自动化发布

避免 lmk123/crx-selection-translate#1125 出现的最好的办法就是琢磨一下用工具自动化发布新版本,这样一来肯定就不会出现把 Firefox 安装包发布到 Chrome 的问题了。但是我找了一圈,似乎没有自动化发布的办法……

扩大单元测试覆盖范围

正是由于代码库越来越大、我对自己的代码越来越没底,所以我开始逐渐给已有的代码写单元测试了。但是,目前仅覆盖了比较核心的功能,而 lmk123/crx-selection-translate#1115 的问题出在组件里,我还没有给任何组件写过单元测试。

顺便在这里吹一下单元测试的好处。我在开发第二个版本的网页全文翻译的文本识别算法(虽然我也不知道叫算法合不合适但姑且就这么叫吧……)的时候,全程使用了单元测试,然后我惊喜的发现,当我在开发过程中考虑代码要怎么写才方便测试的时候,其实是反过来促进我将代码松耦合了。第一个版本的文本识别算法所有逻辑都整合在一起,而第二个版本分割成了三个部分,分别是文本扫描、页面控制和翻译请求,每一个部分都可以单独拿出来测试。

松耦合之后也带来了用户体验的提升,比如在第一个版本中,如果用户切换了翻译服务,那就必须先关闭上一次的网页翻译,然后用新的翻译服务开启一次网页翻译,但第二个版本中就可以做到只切换翻译服务、不用重新开关一次网页翻译了。

起床后再发新版本

发布 lmk123/crx-selection-translate#1125 的时候是凌晨 3 点,发布完我就睡觉了,直到醒过来才看到用户的反馈,但实际上,有用户早在凌晨 5 点的时候就反馈这个问题了。中间 7 个多小时出现问题的用户只能干瞪眼不知道该怎么办,而这个时间本来可以缩短到 2 小时。

为了能在收到用户在 GitHub 上反馈时得到提醒,我本来打算安装 GitHub 的移动端 APP,但突然发现在 App Store 里下架了,于是我安装了之前买过的 CodeHub

LingFeng1226 commented 2 years ago

lmk123/crx-selection-translate#1125 这个问题发生了。。。我木有干瞪眼。。。我离线安装8.5~~~删了更新字段。。说实话,我没第一时间去看游览器开发者模式。而是把重置游览器,各系统问题这些都排除两。才看F12。。。真是失策。。。现在想想感觉也把我教育了。。。

haroldxing commented 2 years ago

自动化部署的话,试试GitHub action?

lmk123 commented 2 years ago

自动化部署的话,试试GitHub action?

@haroldxing Chrome / Edge / Firefox 扩展商店都没有提供发布版本的 API,所有即使在 GitHub Action 里打包了,我还是需要把代码包下载下来然后再手动发到各个扩展商店里,所以没有解决问题。

haroldxing commented 2 years ago

好吧