响应没有回来时:标注写入的幂等与恢复

Sirui Liu Lv4

语言: 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 进行许可。