后台任务取消与数据撤销的边界

后台任务取消与数据撤销的边界

摘要| AI任务越能自动行动,停止按钮就越需要清楚的语义。结合Microi吾码当前后台任务实现,我们把取消请求、执行停止、事务提交与业务补偿拆开,解释为什么“已停止”无法自动撤回此前成功写入的数据。

✦ 一、一个容易误解的停止按钮

假设AI助手正在把一千份资料转成结构化记录。前两百份已经落库,第三批仍在运行。操作者点击取消,通知中心最终显示已停止;刷新业务列表,之前两百条仍然存在。这里最需要解释的是:按钮究竟停止了什么?

关键判断| 取消控制后续执行,撤销处理已经发生的业务结果。两者需要各自的状态和授权。

如果界面只写“取消成功”,用户很容易把它理解为一切恢复到开始前。对能够导入、生成和调用外部服务的AI应用,这种含糊会变成重复写入、误删数据,甚至让下一次重试从错误的位置开始。

✦ 二、沿Microi的调用链看一次取消

Microi后台任务取消的持久状态与执行信号调用链

Microi后台任务取消的持久状态与执行信号调用链

Microi的可靠后台任务由接口引擎承载业务片段,Worker管理领取、租约和执行状态。取消入口先更新共享任务记录,再尝试向本机正在执行的任务发送取消信号。共享记录使停止意图可以被其它执行节点看到,内存信号负责尽快中止当前节点。

当前RequestCancel实现按租户、用户、任务Id和运行作用域筛选记录,排除Succeeded、Failed、Canceled终态。Pending可直接变为Canceled;其它在途状态先显示停止中。这是持久化停止意图,并不是对任意业务表执行删除。

状态与动作| 保存CancelRequested后,Worker仍需要到达能够响应取消的执行点。耗时中的外部服务也可能已经产生结果。

这些边界属于任务执行内核,业务表的补偿逻辑继续留在接口引擎。不能为了一个取消按钮,给平台通用层添加接收任意表名并清空记录的入口。

✦ 三、四种时刻,四种处理

排队、执行、已提交和外部结果未知四种取消边界

排队、执行、已提交和外部结果未知四种取消边界

  • 尚未执行:取消排队任务,阻止它开始下一片。
  • 正在本片事务内:尽快响应取消,并由本片真实执行结果决定提交或回滚。
  • 前一片已经提交:保留真实结果,后续业务按规则选择继续、撤销或补偿。
  • 外部调用结果未知:先凭稳定业务编号查询对方,再决定是否重试。

数据库事务只保护它自己的提交范围。前一片成功提交后,下一片的失败不能穿越时间把前一片一起回滚;第三方已经接收的消息也不会因为本机取消令牌而自动消失。把一小时的工作放进一个大事务,同样无法消除网络与外部系统的边界。

AI工程中的常见误判| 任务Id存在,不等于任务完成;接口超时,不等于对方没有执行;通知中心已停止,不等于历史副作用已撤销。

✦ 四、把长任务拆成可以核对的片段

Microi官方任务规范要求长任务分页处理;预计超过十分钟的任务应持久化检查点并重新入队。每片完成一个能独立确认的小批次,下一片从检查点继续。这个设计同时缩小取消的等待范围,也让重启后恢复有明确依据。

return {
  Code: 1,
  Data: { BackgroundTask: {
    HasMore: true,
    Checkpoint: { LastId: lastId },
    Current: committedCount, Total: totalCount,
    NextDelaySeconds: 1
  }}
};

这里的lastId、committedCount和totalCount由具体业务计算,示例不是可直接粘贴的完整导入程序。检查点记录可恢复的位置;它自身不提供“每条副作用只发生一次”的保证。业务记录仍需要稳定幂等键、唯一约束或条件状态迁移。

片段设计| 让检查点、业务提交与实际工作量对应起来。不要先上报完成数量,再尝试写入数据。

✦ 五、进度条记录事实,不替失败收尾

AI模型的思考时间、第三方等待和数据写入时间不同。一个动画越来越接近100%,并不能说明业务逐项成功。Microi以已提交的Current和真实Total生成进度;总量未知时保留不定进度,失败或取消时保留最后真实值。

V8.Method.UpdateBackgroundTask({
  Current: committedCount,
  Total: totalCount,
  Msg: '本批工作已提交'
});
  • 前端提示“已请求停止”,直到权威任务详情进入终态。
  • 业务列表展示已经生成的数据与对应任务Id,便于定位部分完成结果。
  • 若需撤销,提供独立操作,并显示将受影响的记录范围。
  • 日志记录任务、阶段与业务编号,避免写入Token、密码或模型密钥。

特别要避免把Cancelled画成一个圆满的100%。保留部分完成结果能让用户知道还剩什么,也让运维人员判断应该继续、补偿还是交给人工。一个诚实的进度条比一条看似平滑的动画更有价值。

✦ 六、撤销需要独立的业务账本

对于可撤销的生成草稿,可以用创建任务Id标记记录,并在独立撤销动作里再次核对当前状态:是否仍为草稿、是否已被编辑、是否被其它对象引用。对于通知、外部订单或其它无法原样回滚的副作用,则使用新的补偿动作,保留原始事件和补偿事件。

这里需要业务规则,而不是通用Delete循环。一个任务可能跨越多张表和多个系统;删除主记录可能留下关联记录,删除别人已经修改的结果也会造成新的损失。取消权限与撤销权限应分别校验,且应从当前租户、用户和真实记录状态重新判断。

边界清楚,才便于恢复| 租约减少并发冲突,幂等约束阻止重复结果,补偿处理不可逆副作用。任何一项都不能代替其它项。

✦ 七、本次验证能证明什么

定向源码契约测试通过及其适用范围

定向源码契约测试通过及其适用范围

本次读取了Microi官方任务文档、Job Skill,以及BackgroundTaskService和BackgroundTaskStore相关实现,并执行了一项Worker监督与可观测性的源码契约测试:通过1项,失败0项。它读取当前源码检查宿主注册、取消循环、共享存储和Worker监督等契约。

测试使用已有编译测试宿主,没有重新构建整个平台;它不是连接真实业务库执行取消后撤销的端到端试验,也不能证明某个客户环境已经升级。本文关于已提交结果需要独立补偿的判断来自事务边界与当前调用链,而不是伪造的生产压测。

  • 上线验收应另外覆盖两节点共库、取消过程中节点退出、写入后响应前中断。
  • 最终核对业务记录、检查点和任务终态,而非只看HTTP响应。

如果你正在让AI从“回答问题”走向“替人完成任务”,可以从取消按钮开始检查系统语义:它停止的是未来执行,还是另有明确规则能够撤销已经发生的结果?把这个问题说明白,自动化才更容易让人放心使用。

本文由AI辅助创作;概念图由AI生成。源码分析与定向源码契约测试来自当前工作区,图示不是生产环境测量。

Logo

宁波官方开源宣传和活动阵地,欢迎各位和我们共建开源生态体系!

更多推荐