场景
多级审批平台里,状态机管“走到哪”,这篇补上另一半:该走到哪了。审批链路长、环节多,每个环节有时限要求,但时限没有任何机制兜底——单子停在某环节超了一周,没人知道,也不有人负责。超时的代价不是“慢”,而是流程停摆:上游等结果,下游等材料,谁先着急谁去当人肉催办员。
我实习时负责的二期迭代里,就包含给这条链路补时间维度的功能:逾期预警加工单流转。上线后配套机制随二期版本交付,从效能看板看,评估审批周期平均缩短约 30%——这个数字是组内整体效果,预警和工单是其中一环,不能全记在它头上。
超时检测:定时扫描还是延迟消息
两个可选方案。延迟消息:单子进入某环节时发一条“30 分钟后投递”的延迟消息,到点检查该单是否超时。定时扫描:一个 job 周期性地扫“当前环节 + 环节进入时间”,找出超时的单子。
我选了定时扫描,理由是这里的超时判定天然是可重算的:超时与否完全由“当前状态 + 进入时间 + 时限配置”推导出来,不需要保存任何额外状态。可重算的判定,扫描就是最简单可靠的实现——job 挂了重启再扫一遍,结果不变;而延迟消息要先处理消息堆积、重复消费、时限配置变更后消息作废这一堆边界。
扫描的 SQL 也不难写:单子表上“状态 + 环节进入时间”建联合索引,超时条件就是一次 range 扫描:
SELECT id, status, stage_entered_at
FROM declaration
WHERE status IN (/* 各在途状态 */)
AND stage_entered_at < NOW() - INTERVAL ? MINUTE;
扫描的精度受间隔限制(分钟级 job 最多晚一分钟发现超时),对这个业务完全够用——审批时限以天计,没人在乎预警晚到一分钟。如果时限精确到秒,或者单量大到全表范围扫描不可行,延迟消息才值得它的复杂度。
红黄绿三级:预警的阈值与升级
超时不是二值的。临近超时、轻度超时、严重超时,应该有不同的处置力度,所以拆成三级:
- 绿色:剩余时间充足,不动作,只在看板上可见
- 黄色:超过时限的一半,通知环节责任人
- 红色:超过时限,升级通知管理员,并自动开工单
阈值按“该环节时限的百分比”定而不是绝对时长:材料初审限 5 天、专家评估限 15 天,用同一个绝对值做黄色阈值,等于对短时限环节放水、对长时限环节过度打扰。百分比让“紧迫程度”在不同长度的环节之间可比。
有一条设计纪律值得强调:预警只读状态,不迁移状态。它读取“当前环节 + 停留时长”,算出颜色,仅此而已——状态机里没有“预警”这个分支。这个边界划清楚后,预警系统怎么改、挂了、重启,都不可能弄脏状态机;反过来,状态机对预警系统也只有一个单向的读依赖。两套系统的耦合被压到了最小。
工单:红色预警之后的事
预警解决“知道”,工单解决“有人管”。红色预警自动开一张工单,带上下文(申报单、卡住的环节、超时时长),派给对应环节的负责人;处理人可以是催办、转派,或者反馈一个客观原因(材料不全等企业补正)后关闭。
工单的状态很简单:待处理、处理中、已关闭。关键是闭环的验收口径:红色预警数与未关闭工单数的差值要收敛——每张红色预警都必须对应一张活着或已关闭的工单,这个一致性由开单动作和预警扫描在同一个 job 里保证,而不是靠人工补录。工单看板上“逾期单总数、已开工单、未关闭”三个数字一摆,超时处理的完成度一目了然。
效果
预警与工单流转随二期版本上线。机制上线前,超时单的发现靠人;上线后,红色预警基本在超时后几分钟内就能变成一张有主工单。配套的逾期预警体系对整体审批效率的改善,见前面引用的效能看板数字——机制的作用是让“超时”从无人知晓变成有人负责,效率提升是这个转变的结果而不是魔法。