大型后台管理系统如何把业务操作做可靠(6):批量操作的预览、执行与恢复
运营勾选了全部搜索结果。预览显示 10 条候选里有 8 条可下架。确认前又新增两条匹配商品,计划中的一条则已经被其他人修改。执行时最多只能触达先前确认的 8 条,能否处理每一条还要看当前状态。
先定义选中的范围
交互上至少要分清当前页、用户显式勾选的 ID 和所有匹配结果。后两种可以跨页,全选匹配时还可能排除若干条。预览接口接收选择表达式,用服务端确认过的租户与权限解析目标,将排除、不可见与不可操作分别处理。展示统计时避免用数量透露调用方不可见的记录。页面布局、确认框和失败结果可参考配套的 UX 文章。《后台管理系统常见 UX 问题总结》
保存执行计划,确认时只传计划 ID
下面的示例是预览阶段返回给运营的内容。服务端保存完整计划和 8 条明细,页面可以分页查看,确认请求只引用计划 ID 和本次确认的操作标识。
{
"planId": "P19",
"action": "unpublish_products",
"matchedVisible": 10,
"eligible": 8,
"excluded": 2,
"expiresAt": "2026-11-03T11:10:00+08:00",
"previewSample": [{ "id": "SKU42", "expectedVersion": 7 }]
}
计划关联发起身份、租户、动作、目标及必要版本,确认时校验有效期和操作者资格。一次性计划可以用唯一约束保证只创建一项执行任务。大规模计划可分批持久化明细,或者引用确实能复现目标的不可变快照。仅保存筛选表达式和匹配数量,无法在数据变化后复现原集合。
执行时复核资格和状态
以商品下架为例,可以逐项复核权限、商品归属、版本和当前上架状态,再做带条件的更新。版本变化的记录按产品规则跳过并返回可理解的原因。若同一计划不能容忍部分完成,就在同一事务边界内处理可原子提交的范围。跨系统或跨分片的大批操作通常要设计补偿、人工确认或明确的逐项语义。
| 情况 | 示例处理 |
|---|---|
| 新增匹配项 | 不进入这份计划 |
| 原目标已删除 | 记录目标已不可用 |
| 原目标版本变化 | 跳过并说明需要重新预览 |
| 操作者失去权限 | 依据撤权规则停止后续处理 |
| 执行端崩溃 | 接手后从已提交的逐项结果恢复 |
对于影响大的操作,可以先处理小批次并观察结果,再继续推进。计划支持暂停时,需要说明正在执行的工作单元是否会跑完。对已经生效的下架可以另建恢复计划,并检查下架后是否有新的正常修改。直接把整个商品恢复成旧快照,可能抹掉后来改过的价格和库存。
Atlassian 的 2022 年事故中,原意是清理旧应用,传入的却是整个站点的标识。删除接口接受两类对象,导致 775 个客户受影响,部分客户最长中断 14 天。资源类型应由明确的命令和服务端校验约束,恢复流程也需要实际演练。Atlassian 事故复盘
预览、确认、执行各自保存什么
假设候选是商品 A 到 J,其中 I 和 J 不符合下架条件。服务端保存 A 到 H 的版本和必要的影响信息,页面确认的是这一份清单。如果以后要解释为什么 I 没有执行,预览记录也应保留排除原因,但不要把 I 写进可执行目标。
确认时允许用户从已预览目标中再去掉几项,具体可以生成一份新计划,或者用受约束的子集确认。若操作者添加了新目标,必须再经过预览。服务端校验确认是否属于当前主体、租户和动作,还要保证预览过期后不会被旧请求重新使用。
confirmPlan(actor, planId, confirmationKey):
transaction:
plan = lockPlanWithinTenant(actor.tenant, planId)
requireCanConfirm(actor, plan)
if plan.confirmed:
return matchingExistingJob(plan, confirmationKey)
requireNotExpired(plan)
requireWithinLimit(plan.targets)
job = createJobForPlan(plan.id)
markConfirmed(plan, job.id, confirmationKey)
recordOutbox(job.id)
return job
在这套示例策略中,确认以后计划不会扩张。执行过程中如果 D 版本变化,执行端给 D 写入跳过结果,A 到 H 中其余 7 条继续。运营看到的结算应同时显示「候选 10、排除 2、计划 8、成功 7、跳过 1」,计数都能下钻到具体明细。
恢复也要尊重别人后续的修改
如果七条下架中有三条需要恢复,另建恢复计划并展示哪三条仍可恢复。只恢复上架状态所需的字段,并核对商品当前状态和原操作之间的关系。例如某条商品下架后因违规被另一个流程锁定,恢复动作应拒绝或交给复核。价格在下架后被正常更新,则不应一并重置。
故障后的回退有三个层次。尚未执行的批次可以暂停,已经执行的本地状态可以走有条件的反向操作,已经发送的外部通知则需要业务认可的补救流程。把这三种结果分别记录,事故处置时才能知道还有哪些影响未消除。
用数据变化检验确认是否有效
创建计划以后新增两条匹配项,再修改计划中的一条。确认并执行,应只下架其余 7 条。重复点击确认仍查到同一任务。最后再演练恢复,并保留另一位运营在下架后补写的字段。通过这些例子可以同时检查目标范围、逐项结果和恢复边界。
总结
预览确定操作对象,确认记录操作意图,执行检查当前资格。三步各自保留数据,才能解释为什么确认了 8 条、实际完成了 7 条,以及剩下一条该怎么处理。