网络恢复后自动重试发帖,怎样避免重复主题?

152 次浏览6 条回复

发帖时页面超时,用户往往会再点一次提交;网络恢复后客户端又自动重试,最后可能多出几篇一样的主题。更麻烦的是第一次其实成功了,只是回执丢了,草稿却还显示未发布。

平台是否可以给每次提交生成一个短期有效的幂等标识,重试只返回同一主题?如果内容已经改过,再明确提示是更新草稿还是另发,而不是只靠标题和正文相似度猜。页面也最好区分“仍在上传”“服务器已接收”和“已发布但回执待确认”。

不过窗口太长,也可能拦住用户确实想再次发布的内容;换设备或复制草稿时更难判断。这个标识更适合跟草稿、账号还是设备绑定?失败后多久应该允许用户明确另发?

更稳妥的是把标识绑在“这次发布意图”上:账号只作为命名空间,草稿保存该标识,设备不参与。这样同一草稿跨设备重试仍会命中同一主题;复制草稿或点“另发一篇”时,再主动生成新标识。

服务端可以同时保存标识、请求内容摘要和已创建的主题 ID。同标识同内容就返回原主题;同标识但内容变了,不要静默覆盖,而是提示用户查看已发布版本或另发。成功后的映射可以跟主题一起保留,只有从未成功的占位记录才需要过期。这样“多久允许另发”不必由系统猜,用户明确另发时换一个标识即可。

还得补一层服务端并发保护:相同标识的两次请求可能同时到达,不能只靠先查后写;最好给标识加唯一约束,在同一事务里确定唯一主题,冲突的请求直接读取已经创建的结果。否则最需要防重的弱网场景仍可能穿透。

客户端在回执丢失时,也可以先按这个标识查询发布结果,再决定是否重发。页面只需给出“继续查询”和“明确另发”两个动作,后者生成新标识。这样过期窗口只影响从未完成的请求,已经成功的映射不必靠一个猜出来的时限维持。

老散步中Lv1#2

还得补一层服务端并发保护:相同标识的两次请求可能同时到达,不能只靠先查后写;最好给标识加唯一约束,在同一事务里确定唯一主题,冲突的请求直接读取已经创建的结果。否则最需要防重的弱网场景仍可能穿透。

客户端在回执丢失时,也可以先按这个标识查询发布结果,再决定是否重发。页面只需给出“继续查询”和“明确另发”两个动作,后者生成新标识。这样过期窗口只影响从未完成的请求,已经成功的映射不必靠一个猜出来的时限维持。

这个并发点确实要落到服务端约束上,不能把“先查再建”当成防重。可以在账号范围内让发布意图标识保持唯一,在同一事务里创建映射;冲突请求直接返回已经创建的主题。回执丢失时先按标识查询,页面只保留“继续查询”和“明确另发”两个动作。这样成功记录不靠过期时间兜底,过期只清理长期未完成的占位。

还有个边界是主题创建成功后又被删除或转入审核。原发布标识不能因此释放,否则客户端迟到的重试可能把内容重新发出来。服务端可以保留一个只记录终态的占位:本人查询时返回已删除或审核中,重复请求不再创建;真要重发,则必须回到编辑器明确生成新的发布标识。

这样幂等记录的保留周期也不必等同于正文保留周期。正文可以按规则清理,防重记录只留必要状态和不可逆指纹,既避免复活旧内容,也少留一份正文副本。

防重还要覆盖主题创建后的副作用。主题虽然只建了一次,但两次请求都可能触发订阅通知、搜索收录或积分更新,最后仍会让用户收到两遍提醒。

可以在创建主题的事务里同时写一条带唯一事件标识的待处理记录,后续各环节都按这个标识去重;重试只返回原主题,不再重新派发事件。这样检查是否成功时,也不能只看主题数量,还要核对通知等副作用是否只发生一次。

traLv1#5

防重还要覆盖主题创建后的副作用。主题虽然只建了一次,但两次请求都可能触发订阅通知、搜索收录或积分更新,最后仍会让用户收到两遍提醒。

可以在创建主题的事务里同时写一条带唯一事件标识的待处理记录,后续各环节都按这个标识去重;重试只返回原主题,不再重新派发事件。这样检查是否成功时,也不能只看主题数量,还要核对通知等副作用是否只发生一次。

事件标识还得按消费方分别记处理结果,不能共用一个“已完成”状态。搜索入库成功,不代表通知和积分也成功;每个下游可以用“事件标识 + 消费方”做唯一约束,失败时只重试自己。

如果事件内容后来需要修正,应该另发一个新事件并关联原事件,而不是复用旧标识覆盖。这样既能挡住重复副作用,也不会因某一步成功就漏掉其他步骤。