06 · 开发 · 事务
先写拒绝,再写成功
后端工程师让一次完工入库在同一秒内决定:过账、记流水、待回写,要么一起成立,要么一起当没发生。他不在浏览器里改库存,也不对金蝶直接插入。
- 09:10 看半成功。 在制品已经扣了,工单仍是待报工。先标数据,不盖新代码。
- 11:00 收事务。 在制品、完工库存、工单状态同一事务。任一步失败一起撤回。
- 15:20 收幂等。 同一请求号重放,返回第一次的结果,不再插入。
- 17:40 拆回写。 金蝶超时只重试回写,不重试本地库存。
后端工程师守的是规则能否被重复执行
产品写「超计划必须拦下来」,后端工程师把它变成服务端行为:未确认的请求返回业务错误,不改库存;确认单号写进同一事务;重复提交不会加第二次。岗位特点不是接口数量,而是成功和失败都说得清。权限是班组长才能放超计划。日志是第二天能查出谁在几点报的这张工单。幂等是连点两次只入账一次。夜班超收那一笔现场事实,由业务分析师记录,本岗不重写那一晚。
他和前端工程师的边界:前端展示拒绝原因,不在浏览器里把库存加上。他和数据库工程师的边界:数据库工程师管表结构、索引、约束和备份,后端工程师决定这笔业务写哪些表、按什么顺序写、失败时撤回哪些。他和集成工程师的边界:对方字段和方向由集成对,本地在回写前必须先落到待回写,不能先显示已完成。金蝶里会不会出现两张草稿,是集成的实验,后端只保证本地事务先一致。
拒绝条件要能被测试调用
每一种业务拒绝都有稳定错误码、业务可读的原因和单据号。笼统的 500 会让前端只能显示失败。系统故障和业务拒绝必须分开。调用方如果把别人的车间编号写进请求,必须被拒绝并留下审计,而不是返回空列表假装没有工单。
完工入库半成功怎样收场
注塑车间把一张工单报成完工。规则是超计划不能直接入可用。班组长连点两次,页面失败。白班发现在制品少了、成品多了一截,工单仍待报工,金蝶没有这张单。日志显示第一次已经写了流水,回写超时,事务没有整体回滚;第二次被唯一约束拦住,却返回了笼统失败。
修复在服务端做完三件事。在制品扣减、成品增加和工单状态放进同一事务。请求号重复时返回第一次结果。回写改成独立队列,本地账先一致。重放那张工单:第一次入账并留下待回写,第二次结果不变,超计划部分仍待确认,不进可用量。规则是否允许超计划,不是后端私自放宽的。他要保证系统不会在「不允许」的同时把账改了。工单号、请求号、车间和操作者写进拒绝日志。找不到单号的日志,对这个岗位来说等于没有日志。
超计划的确认如果发生,确认单号必须和原工单进同一事务。确认写了、库存没动,或库存动了、确认没写,都是半成功。权限在服务端再查一次:把别人的车间编号写进请求,必须拒绝并留审计,不能返回空列表假装没有工单。笼统 500 会让前端只能显示失败,运维和班组长会用同一种处理。业务拒绝和系统故障分开,是后端给前端的契约。金蝶会不会出现两张草稿,仍由集成用幂等号证明;本岗只保证本地在制品、成品和工单状态先一起成立。