后台任务状态机:让排队、取消和重试可解释
舒心读
18
卷中目录
后台任务只有“进行中”和“完成”两个状态时,操作者很难判断它是在等待资源、正在计算,还是已经失败却没有更新界面。更清楚的状态机,能让恢复和交互使用同一套语言。
本篇目标: 为一个虚构的图片处理任务定义状态与转换,分开任务身份和执行尝试。

先写出每个状态的进入条件
queued 表示已接受但尚未开始;running 表示某次尝试获得了执行资格;succeeded 表示结果已经保存并可读取;failed 表示本轮无法继续;cancelled 则需要说明任务已经停止到哪个边界。
状态名本身不重要,进入条件必须明确。例如结果文件还未持久化,就不应先把界面改成成功。
任务 ID 与尝试 ID 分开
同一任务可以有多次尝试,但每次尝试都需要能够被区分。工作者提交结果时,服务器应确认它仍属于当前有效尝试,避免旧工作者的迟到结果覆盖新状态。
{
"jobId": "demo-job",
"attemptId": "attempt-b",
"state": "running",
"cancelRequested": false
}
这些标识是演示值。实际系统还需要校验领取资格、租约或版本,以及结果保存的原子性。
取消是一段过程
请求取消不一定能立刻中断底层操作。可以先记录取消意图,再由执行者在安全边界检查。已经发送给外部系统的动作,也不会因为状态改成 cancelled 就自动撤回。
界面应告诉用户正在取消、已经停止或无法撤销,避免用同一个“已取消”覆盖不同事实。
把转换写成可检查的表
可以先列出允许的边:queued 到 running、running 到成功或失败、可恢复失败到再次排队。终态回到执行态是否允许,应通过明确的新命令或新运行记录完成。
测试不仅检查正常成功,还要让旧尝试晚于新尝试返回、在保存结果前退出、在取消后收到成功回调、重复处理同一结果。恢复后保留错误原因和已完成阶段,操作者才有依据决定继续、重试或终止。
见字如晤