同一条文档回调收到两次,如何做到只处理一次

同一条文档回调收到两次,不应触发两份任务或两次追加写入。可靠的处理需要两层保护:接收层识别重复事件,业务层识别重复动作。仅在内存中记住最近一次消息,无法覆盖进程重启和并发投递。

事件去重解决的是接收身份

如果事件源提供稳定事件 ID,可以持久记录该 ID 的接收与处理状态。重复投递到达后,查询已有记录并继续原状态,而不是新建一条完全独立的工作。去重键还应包含事件源或租户作用域,避免不同来源使用相同 ID 时相互误伤。

Stripe 的 webhook 文档明确讨论了重复事件,并建议记录已经处理的事件 ID。它还区分同一事件重发和两个事件对象指向相同业务变化的情形。文档平台是否具有相同模型,需要根据真实回调协议确认,不能自行猜测一个通用去重字段。

收到与处理成功是两个状态

若收到回调就标记“完成”,随后程序在创建附件前退出,重投递将被忽略,业务动作永远不会发生。另一种错误是直到所有动作结束才登记事件,于是两个并发请求可能同时开始工作。应使用可验证的状态转换保存接收、处理中和处理完成。

状态重复到达时的处理
已持久接收,待处理复用队列项
正在处理避免并行启动同一工作
已确认完成返回已有处理结果
上次结果未知先查询已发生的业务动作

业务幂等覆盖不同事件触发同一动作

例如文件上传完成通知和人工点击“生成预览”都要求导出同一个版本。事件 ID 不同,但预期产物相同。可以用文档 ID、输入版本、转换规格和业务意图构建操作身份,复用已有结果。不同版本或不同导出规格则应该产生独立任务。

不要用“同一文件今天只处理一次”作为宽泛去重条件,这可能吞掉当天真实的后续修改。也不要把正文内容相同当作唯一重复证据,因为不同项目可能合理地使用同一模板。去重键必须与具体业务动作的等价条件一致。

用四种重复验证实现

串行重投递、并发重投递、处理后重启再投递,以及两个不同事件触发同一动作,都应进入验收样本。检查队列数量、实际文件数量和最终业务状态,并确认重复消息有可查询的处理记录。

回调接收成功只说明系统接受了消息,不代表文档处理完成。交付界面和运行报告应保留这一区别。这样即使平台不断重试通知,团队仍能知道真实工作是否发生、在哪里发生,以及哪些项目还需要继续恢复。

事件去重与业务幂等分层
根据本文方法绘制的原创流程示意;不是产品界面或实测结果。

在企业文档中验证

如果要把本文方法用于企业文档,可预约演示,结合实际资料核对协作、权限与集成方式。

需要在自己的环境中验证时,可先了解私有化部署方案,再确定试用范围与验收要求。

参考资料

相关文章