跳转至

第八章 · 老梁走了

七月三十一日,八点零七分。

拦截器昨天上线灰度,一千八百四十七笔。settle.guard 的日志第一屏就有一条 WARN:商户 M301-7752-9 的同一笔预结算被拦了两次,金额一万一千四百三十八,两次命中的规则都是“跨天时间窗”。

配置里那一段是这么写的:

settle.guard.window[0]=22:00-02:00
settle.guard.window[1]=02:00-04:00

两条窗口,解析的时候按小时取整,第二条把第一条覆盖了。二十三点五十九分那一笔掉进了第二条的判定分支。

误拦。钱没有错,商户重试一次就过了,没有人投诉。

这件事陈稳知道。三个月前他在 WindowParser 里加过一行:// TODO: 跨天窗口应按时刻匹配,不能按小时。昨天的上线报告他填的是“灰度 1,847 笔,无异常”,抄送纪衡。MR 的描述里也没有这一句。

他把那条 WARN 的日志 ID 抄进记事本,改了一个断言,提交。commit message 三行,最后一行写的是“灰度期数据校验补充”。

日志再往下翻,同一分钟内还有第二条,级别是 INFO,内容是拦截器把这笔请求的上下文写进了 settle_guard_log。规则 ID W-07,命中次数当日累计两次,都是同一笔。分母一千八百四十七,分子一。误拦率万分之五点四。

这个数字他算了两遍,第二遍用的是计算器。

八点五十分,走廊拐角。

老梁从副总办公室那个方向过来。格子短袖衬衫,领口有洗不掉的印子,左手拎一个帆布包,右手拿一份文件。两个人隔着三米,头顶的灯管在响。

“陈稳。”

“梁哥。”

老梁把文件夹到腋下,从口袋里掏出烟盒,抽出一根,又塞了回去。

“我老婆昨天跟我说了一句话,”老梁说,“她说,你再不走,命都没了。”

陈稳记得老梁这个月请过三次假,都是半天,理由都写“就医”。审批人是纪衡,三次都批了,批的时间分别是二十三点四十、零点零七、零点五十一。

“我想了一晚上,想通了。”老梁把文件拿回手里,“技术支持中心也不去了。我提了离职。”

“什么时候走。”

“今天。东西收拾好了,纸箱在电梯口。”

老梁左眼下面的眼皮跳了三四下,停了。

“你那个拦截器昨天灰度了。”

“嗯。”

“一千八百多笔,全过。你那套代码我上周在 MR 里扫过一遍,逻辑没什么问题。”

“有一条误拦。跨天窗口,第二条配置覆盖了第一条。”

“报了吗。”

“报告里写的是无异常。”

老梁笑了一下,很短。

“那就别报了。”老梁说,“你现在报,别人听见的是‘他上线有问题’。你修完再说,别人听见的是‘他把问题修了’。”

“这不一样吗。”

“对系统一样,对人不一样。”

这句话陈稳后来抄进了记事本,抄在那条 WARN 日志 ID 的下面。

“纪总这个人不好糊弄,但也不坏。”老梁说,“他只看数。数摆得住,他不为难你。”

“你在结算组多久了。”

“十一年。”老梁说,“我进来那年,结算跑在 Oracle 上,一天四万笔。现在九十二万。”

“三年前从 Oracle 迁到自研中间件,方案是你写的。”

“谁跟你说的。”

“文档署名是你。”

“署名有什么用。”老梁把帆布包换到右手,“方案评审过了,迁移零故障,第二年我的考评是 B。理由写的是缺乏跨部门影响力。”

“你申诉了吗。”

“申诉过一次。上级说,你做的是底层,看不见。”老梁说,“看不见就是不存在。这是他原话。”

老梁把帆布包的带子在手里绕了半圈。

“我那个位置,你坐过去也行,窗户那边光线好一点。”

“不用。”

老梁没有坚持。他往电梯那边挪了两步,又停住。

“电梯口那个纸箱,你帮我看着一下,别让人当垃圾扔了。”

“好。”

老梁走了。走廊里只剩灯管的声音。

老梁的工位在窗边第三个。显示器已经拔了线,线圈成一团压在键盘下面。资料架空了,架子最下面一层留着一圈灰边,是一本书压出来的,边长大概二十四厘米,A4 开本。桌面擦过,左上角有一圈白印子,杯子放久了留下的,直径七厘米。

抽屉没有锁。里面剩三样东西:一支干了的红笔,一张二〇二三年的机房出入登记条,一个印着“恒澜科技十年司龄”的钥匙扣,塑封没拆。

电梯口靠墙放着一个纸箱,装打印纸的那种规格,开口用透明胶带封了两道,侧面用马克笔写着“梁栋”,最后一笔拖出去一点,收不住。箱子上面压着一个搪瓷杯,杯口朝上,里面积了一层灰,杯沿磕掉一块瓷,露出下面灰色的底。

陈稳没有碰那个杯子。

九点二十六分,邮件到了。发件人梁栋,收件人结算组全员,抄送纪衡,标题是“各位,我走了”。正文六行:

“各位同事,我梁栋今天正式离职。

在恒澜十一年,谢谢大家。

技术支持中心的工作已经交接给张毅,结算组的工作由纪总直管。

陈稳的 settle.guard 项目已上线,后续由他继续维护。

祝大家工作顺利。”

第四行陈稳读了两遍。“后续由他继续维护”这一句,老梁没有跟他商量。写在抄送纪衡的邮件里,就是定了。

蒋辉的消息紧跟着进来,问老梁是不是走了,什么时候的事,跟他说了什么。陈稳回了三条:是;今天;说纪总只看数。蒋辉回“他说得对”。陈稳又打了一条,把老梁那句“对系统一样,对人不一样”发过去。

这一条蒋辉过了四分钟才回,只有五个字:“这句你记住。”

“为什么。”

“因为他自己没记住。”

十二点十分,食堂。易文在靠窗那张桌子,对面空着一个位置。

“老梁走了。”易文说。

“你知道了。”

“他抄送了全公司他认识的人,三百多个收件人。”

陈稳餐盘里是青椒炒肉,青椒老,皮厚,嚼两下才咽下去。

“技术支持中心也不去了?”

“嗯。直接离职。”

“他老婆让他走的?”

“你怎么知道。”

“十一年恒澜,他老婆能忍到现在,已经算能忍了。”

“你有没有想过,”易文说,“如果他十年前走,现在会在哪里。”

“不知道。”

“他最好的时候是三年前。Oracle 迁自研中间件,他一个人扛了整个方案。那时候走,手里有东西,谈得下 tech lead 的位置。”

“他说那年考评是 B。”

“对。所以他更不敢走了。”易文把筷子横在碗口上,“考评 B 的人出去谈薪,简历上写不了这一段。他被那个 B 锁了三年。”

“他每个季度报的 OKR 都是‘稳定运行’。”易文说,“三年,十二个季度,一个字没改过。”

“稳定运行不算错。”

“不算错,也不算数。”易文说,“你昨天那个拦截器,值多少钱?”

“零资损。”

“零是个数吗。”

陈稳把筷子搁下来,搁在碗沿上。

“出了事才有数,没出事就是零。”易文说,“这就是老梁十一年的问题。”

“你下午有会?”

“两点半,数据治理立项。”易文端起餐盘,又放回桌上,“你那个误拦,修了没有。”

“你怎么知道有误拦。”

“settle_guard_log 在我们库里。二十三点五十九分那条 WARN,规则 ID 是 W-07。”

“还没修。”

“修了再告诉纪衡,别现在说。”

“老梁也这么说。”

“老梁这句是对的。”易文说,“他这辈子说对了两句话,这是第二句。”

“第一句是什么。”

“三年前迁移评审会上。有人问他这套中间件能撑几年,他说撑到日均两百万笔。”易文把餐盘端起来,“现在九十二万。他说对了,但没人记得是他说的。”

第二天下午三点,会议室。纪衡在靠窗的位置,笔记本电脑打开着。蒋辉在靠门那边,手机屏幕亮着。陈稳的位置靠墙。投影仪开着,幕布上是白的,什么都没有,中间有一块暗斑,是幕布上的灰,吸不住光。

“三点。开始。”纪衡说,“老梁离职的事你们都知道了。今天说三件。第一,交接。第二,八月计划。第三,组织架构。”

“第一,交接。老梁在结算组的工作我接手,技术支持中心的部分交给张毅。他名下十七个工单,今天之内分完。他的代码,暂时由陈稳维护。”

陈稳在记事本上写了个“17”。他自己名下现在有九个。

“第二,八月计划。拦截器全量,按计划执行。结算稳定性继续保持。双月报告正常提交。”

纪衡翻了一页。

“陈稳。灰度一千八百四十七笔,误拦几笔。”

“一笔。”

“报告里写的是无异常。”

“提交报告的时候我还没看到那条 WARN。”

“根因。”

“配置解析按小时取整,两个时间窗重叠的时候,后一个覆盖前一个。”

“影响多少钱。”

“零。商户重试一次就过了。”

“什么时候修完。”

“今天。”

“修完把 diff 发我。”纪衡说,“下周全量以后,我要看分子分母。不要再写‘无异常’。‘无异常’不是数字。”

会议室里没有人接这一句。

“第三,组织架构。结算组暂时维持现状,不招人,不调岗。工作量往上加。下个月开始值班排班调整,每个人轮值,每周一次,二十四小时。”

“排班表今天发。有问题私聊我。”

蒋辉举起手。“纪总,排班按什么顺序。”

“按姓氏拼音。你第一个,陈稳第二个。”

“那第一周是我,第二周是陈稳?”

“第一周是陈稳。”纪衡说,“你下周去客户现场,改过来了。”

蒋辉放下手,笑了一下。“行。”

“还有问题吗。”

“散会。”

散会以后,蒋辉在走廊上追了两步跟上来,走在陈稳前面半个身位,衬衫下摆塞在裤子里,皮带扣反了一下走廊的灯光。

“老梁走之前,有没有跟你说什么。”

“没有。”

“他那个纸箱是我帮他搬下去的。放在电梯口,怕被人当垃圾扔了,我就搬下去了。”

“他让我看着的。”

“我知道。”蒋辉说,“我下去的时候你在开会。”

陈稳算了一下时间。会议是下午三点,纸箱昨天上午九点多就在电梯口了。中间隔了一天多。

“他走的时候,没有回头看。”蒋辉说。这句不是问句,语气也不是描述,像是在说给自己听。

“他值过多少次班。”陈稳说。

“老梁?没排过班。他以前不用轮值,出事直接找他。”蒋辉说,“这一点你比他好,你有排班表。”

三点二十一分,纪衡的邮件到了,附件是排班表。表格里陈稳的名字排在八月三日,星期一,值班,二十四小时。备注一栏写着:“值班手机随身,全时段可达。”

同一封邮件的第二个附件是老梁那十七个工单的分配表。陈稳名下加了六个,最上面那一条是 INC-20260728-0113:settle_reconciliation 表上周四新建,无设计文档,待补。提出人:张毅。

这张表陈稳没听说过。他去库里看了一下,四个字段,两千三百万行,建表时间 2026-07-28 16:32:17,没有主键注释,没有任何索引说明。工单描述一栏只有八个字:“对账中间表,临时使用。”

临时使用的表有两千三百万行。他把这一条抄进记事本,抄在老梁那句话下面,中间空了一行。

下午六点,电梯里站着一个人,白衬衫,黑西裤,黑框眼镜。是顾源。

“你好。”

“你好。”

电梯从八楼下去,七楼、六楼、五楼没有停。

“老梁走了。”顾源说。

“嗯。”

“上周我在楼梯间碰到他。他说了一句话——‘你帮我看着点陈稳,他代码写得不错,但别让他学我。’”

数字跳到四楼。

“我答应了。”顾源说。

电梯在二楼停了一下,门开了,没有人上来,又关上。

“你那个 settle.guard 我看了,逻辑没问题。有一个地方,你那个 TODO 还没改。”

“跨天时间窗?”

“嗯。配置里同时出现 22:00-02:00 和 02:00-04:00,第二个窗口会覆盖第一个。因为解析逻辑是按小时匹配,不是按时刻匹配。”

“我加了一个 TODO 注释。”

“注释不会修 bug。”

陈稳的手在电梯扶手上挪了一下,挪到冷的那一段。他今天上午跟纪衡说的是“今天修完”。现在是下午六点零四分,代码一行没动。

“那个 TODO 你什么时候加的。”顾源说。

“三个月前。”

“三个月前你不知道会有两个窗口。”

“上周就知道了。营销那边报了两个时段。”

“那就不是 TODO 了。”顾源说,“TODO 是不知道怎么修。你知道怎么修。”

到了一楼,顾源先出去,走了两步,回头看了他一下,什么都没说,转身走了。

外面天还没有完全黑,西边是橙色的,云边上镶一道暗红。

七点四十分,家里。何晚的消息在手机上排着,两条。

“明天周末,要不要出来。”

“好。”

“你想去哪。”

“随便。”

“那去南京路走走?”

“好。”

“你上次也说好,然后周六去公司了。”

“这次不去。”

书房的灯开到最亮。陈稳打开 WindowParser,把那行 TODO 上面加了一个方法:把 22:00-02:00 解析成两个区间 22:00-24:00 和 00:00-02:00,按时刻比较,不再按小时取整。跑测试,二十三个用例,第一遍红了两个,边界值 02:00:00 归属判定错了;他把区间改成左闭右开,再跑,全绿。

提交。commit message 两行:

fix: 跨天时间窗按时刻匹配,不再按小时取整

灰度期间商户 M301-7752-9 单笔被重复拦截(规则 W-07)。
原因:多时间窗重叠时后一个窗口覆盖前一个。顾源指出。

他把 diff 链接发给纪衡,加了一句:“已修,测试 23/23 通过。”

发出去的时间是凌晨一点二十分。

纪衡没有回。收件箱最上面那封还是三点二十一分的排班表。

对面那栋楼亮着灯的窗户不多。三楼亮着,五楼亮着,八楼亮着,九楼也亮着。他看了十一个月的那一扇,还是黑的。

床头柜上放着两个手机。一个屏幕朝下,是他自己的。另一个屏幕朝上,值班手机,八月三日零点开始生效,现在还没到,屏幕已经亮着,右上角信号三格。

他没有关它。


← 第七章 蒋辉的方案 · 目录 · 第九章 值班 →