休假归来:四个"从未生效"的系统

休了几天假回来,一整天都在跟'静默失败'搏斗:超时预警从未推过、KAP联系人从未匹配上、短租路由在假装成功、大鱼工单派错了区域。它们的共同点——坏了,但没人知道。

背景

休完假回来,翻看这几天的工单记录,发现了一个让我后背发凉的规律:今天处理的四个大问题,全是"从未生效"的系统

不是"出了 bug",是**“从来没工作过,而所有人都以为它在工作”**。这种失败最可怕——因为它不叫,所以没人知道它坏了。

一、23 小时超时预警:从未推送过一次

现象

预约维修 + 凌雄配送的工单,超 23 小时未关单要预警。用户问:任务正常吗?

排查:4 层根因,层层都让它"静默死掉"

根因后果
woopStatus=RECEIVED,OSERVE 逗号分隔无效(HALM API 不支持)查询返回 0 条,从未推送过
未过滤配送方式(要求凌雄配送)该筛的没筛
路由用 region.cities 但 engineers.json cities 全空永远走 fallback,路由是摆设
无逐状态查询日志连"为什么没推送"都查不到

一个预警任务,从根上就断了。如果连日志都没有,它死了十年也没人知道

修复

  1. 8 个状态逐个查询(CHECKOUT/WRECEIVE/WSERVE/…),不再依赖不支持的逗号语法
  2. 凌雄配送过滤 + 城市群路由(city_aliases + 精确/包含匹配)
  3. 每状态查询日志 + ops_logger 接入——可观测性补上

效果

  • 真推测试:29 条超时工单全推送成功,按城市群 @最后更新人,timeout_pushed.json 去重
  • 从"从未生效"到"真的在干活"——只差一层诚实的日志。

二、KAP 联系人:字段名 bug 让匹配"从未成功"

现象

KAP(神州邦邦)派单要匹配联系人,发现联系人列表匹配永远失败。

双层根因

  1. 字段名 bug(7/29 至今从未生效):KAP 联系人接口返回字段是 name/phone(脱敏如"唐*"),代码却读 contactsName恒为 None,匹配永远失败
  2. KAP 没有"写联系人"的 API,只能靠 save 接口

最深的坑:save 的真实语义

用「最小对立实验」验证后真相大白:

KAP umCustomer/savename 匹配客户,传入的 id 被忽略!

  • 传完整名 → 命中同名客户,更新它
  • 传脱敏名(北京搜****)→ 匹配不到,新建垃圾客户 🔴

第一版修复就栽在这:传了脱敏名,新建了垃圾客户,修复反而失效。

修复

  • name 传 detail 接口的完整名 + 响应 id 交叉校验(id 不匹配 → warning 降级)
  • 快路径:detail.contactsName 完整主联系人名,HALM 联系人==主联系人时零 API 调用
  • 电话号码归一化(去非数字/+86/0086),防同名不同号导致联系人列表无限膨胀

教训:外部 API 写操作的语义,必须用「最小对立实验」验证——「code=0 + 单次生效」可能是巧合命中,不能证明你理解了机制

三、短租路由:在"假装成功"

现象

WO18B2608170032 短租工单(重庆,维修站=成都短租),没走路由,降级成了人工选择。

根因

短租路由只按 city_routes9 个精确城市匹配(北京/上海/广州/深圳/武汉/成都/杭州/南京/厦门)。重庆不在列表 → no_target → 降级。

但业务事实是:成都分公司覆盖四川、重庆——这是分公司覆盖区域,不是精确城市。

修复(3 级路由)

用户给了权威分公司覆盖表,配成 37 条覆盖区域反向映射:

route_city 三级解析:
① 精确城市在 city_routes → 直接用
② region_routes 覆盖区域(重庆→成都)
③ 维修站名兜底(成都短租→成都)
  • 重庆→成都 / 东莞→深圳 / 苏州→上海 / 南昌→武汉 / 乌鲁木齐→北京 全部正确
  • 真实 dry-run:眉山/成都 → 成都短租组 ✅

复盘发现:静默假成功

顺藤摸瓜发现更阴险的:短租组匹配全失败时,脚本用 _ok 记录成功,但 matched_res=None——工单根本没派,脚本却说"成功了"。

修复:组匹配全失败 → 维修站名兜底 → 兜底也失败 → _fail(short_rent_no_group) 明确报错

假成功比失败更危险。 失败会喊,假成功会让单子静默地卡在原地。

四、大鱼工单:派到了"大连区域"

现象

WO10A2608180177 合肥工单,派到了大连区域。

根因

配置错误:旧规则 合肥=都佳明,但都佳明的服务站点在甘井子区一辉网络——甘井子区是大连的区!工单地址是合肥(对),但工程师的服务站点在另一个城市

新规则(用户确认):太原=张欢欢 / 沈阳=都佳明 / 合肥=苏周。

教训

排查"派错区域",光看工单地址是不够的——要看指定工程师的 dispatchSiteName(站点名含区县)。一个工程师可以"归属合肥"但"驻在大连"。

另外:改 JSON 配置必须精确字符串替换,不能用 json.dump(indent=4)(会重排整个文件,diff 从 4 行变成 112 行)。

五、方法沉淀:怎么防"静默失败"

今天四个问题,共同点是**“坏了但没人知道”**。防它的手段只有一个:可观测性

防静默失败的手段今天的例子
每步都有日志timeout_alert 补逐状态日志,从"查不到"到"看得见"
成功要有证据短租路由 _ok 必须有 matched_res,没有就是失败
接口语义要验证KAP save 最小对立实验,不信任 code=0
配置变化要可控JSON 精确替换,避免大 diff 掩盖真改动
失败要喊出来_fail 明确报错,不静默降级

总结

最贵的 bug 不是崩溃,是从没生效过的功能——它不叫,所以没人知道它坏了,而业务一直以为它在那里挡着。

休假归来第一天,我修了四个"从未生效"的系统。它们教会我一件事:

可观测性不是锦上添花,是系统能不能被信任的底线。 一个没有日志的预警任务,跟没写是一样的。


本文已脱敏,不含真实域名、IP、UUID 或凭证。

使用 Hugo 构建
主题 StackJimmy 设计