响应没有回来时:标注写入的幂等与恢复
语言: English | 简体中文
发布日期:2026-10-09
我为 Concept Review 加入持久化幂等与恢复机制,让 HTTP 响应丢失时,用户无需猜测操作有没有写入。设计连接 SQLite 回执、请求身份与浏览器显式恢复流程。
工程重点:API 幂等、事务和前端恢复。
一次普通审阅是浏览器发 POST、服务器提交、响应返回。但连接断开、设备休眠或代理超时时,最后一步可能永远不到达。此时真正的问题是:写入发生了吗?
为什么只读当前状态不够
FLH-028 在实现前先调查这个问题。可控代理覆盖全部十一种标注操作及根路径、/api 两种路由,模拟三类故障:不转发请求、提交后丢掉响应,以及暂缓原请求、让核对读取先完成。104 个场景的行为都与代码一致。
调查也明确了读取证据的边界:membership 只能证明当前归属,不能证明是本次请求写入;空 membership 无法区分“从未存在”和“本次刚清除”;DISTINCT 与关系操作每次追加事件,核对读取后仍在途的原请求可能继续追加。因此,不能仅靠读取决定是否安全重试。
一个 key、一份回执、显式重试
FLH-029 先覆盖重复会追加事件的 DISTINCT、BROADER、NARROWER、RELATED:
- 客户端可发送数据库全局范围的规范 UUID
Idempotency-Key。 - Migration 009 中的回执与标注事件写入同一 SQLite 事务,查回执前先取得写锁。
- 同 key、等价内容返回原来的
201结果,不重新评估当前状态;不同 payload 或 action 返回409,不写入。 GET /annotation-operations/{id}读取提交回执。404只表示未知,不代表取消,也不允许换新 key 盲重试。- 不带 key 的调用保留旧行为。
浏览器在发送前保存最小且版本化的操作描述,包括 key、action、目标和 relation。重新加载后可以恢复未知操作,但不会自动发送。用户可以查回执,或显式原样重发,即使当前 UI 选择已经改变。
回执归因和重新读取当前状态是不同步骤。“提交已确认,但刷新失败”就按这两个事实显示。
验证发现了什么
作者检查覆盖定向与全量 Go 测试、make verify 和前端测试;该环境没有真实浏览器。FLH-030 随后在开发与生产构建各执行浏览器验收:24 项脚本检查通过,回执和事件一致,没有自动重发。
同时发现三个前端问题:另一标签页的未知操作被误报为 storage failed,且阻止全部 unit;页面离开后到达的拒绝没有清理未知状态;存储恢复后按钮看似可用但无动作。
FLH-032 将提示限制到对应 unit,确保 unmount 后仍清理拒绝结果,并加入显式 Recheck browser storage。新测试在缺少修复时失败,修复后两种构建的浏览器检查再次通过。
FLH-031 由原作者复核合同,发现的是证据工具问题:工具链归因不准确、Compose image name 可能无效、代理合并了重复 header。FLH-033 修正这些 harness,而没有把作者复核称为独立审查。
恢复合同的范围
这个阶段没有多标签锁、回执过期或取消,也没有给 SAME、重新归属、INVALID、Concept 创建和 preferred-unit 修改加 key。回执保存在数据库,恢复较旧备份可能丢掉较新回执;清空浏览器存储也会丢掉恢复身份。
实现结合 AI 编码工具,由我负责方向、任务与审查。
源码与证据
- 标题: 响应没有回来时:标注写入的幂等与恢复
- 作者: Sirui Liu
- 创建于 : 2026-10-09 12:00:00
- 更新于 : 2026-10-25 12:00:00
- 链接: https://vanquisher.world/zh-CN/2026/10/09/flh-lost-responses/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。