跳转至

实验:Tool 幂等

预计:60 分钟|验证:相同 operation_id 只产生一次副作用

场景

Agent 调用 create_ticket,第一次成功,但响应丢失。Agent 重试后不能创建第二张工单。

最小数据库

CREATE TABLE tool_executions (
  operation_id TEXT PRIMARY KEY,
  status TEXT NOT NULL,
  result_json TEXT
);

CREATE TABLE tickets (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  device_id TEXT NOT NULL,
  reason TEXT NOT NULL
);

处理流程

收到 operation_id
→ 尝试插入执行记录
  ├─ 已存在 → 返回保存的结果
  └─ 成功 → 创建工单
             → 保存结果
             → 返回

必做测试

测试一:顺序重复

连续调用两次:

{
  "operation_id": "task-1:create-ticket:device-1001",
  "device_id": "1001",
  "reason": "frequent-offline"
}

断言:

  • 返回同一个 ticket_id;
  • tickets 只有一行。

测试二:并发重复

让两个线程同时提交相同 operation_id。只在应用层先查询再插入会产生竞争;数据库唯一约束应成为最后防线。

测试三:不同业务操作

更换 operation_id,应该创建新的工单。

需要思考的失败窗口

如果插入 running 后进程崩溃:

  • 谁接管?
  • 多久视为超时?
  • 外部副作用是否已经发生?
  • 怎样查询外部系统的已有结果?

幂等不是加一个 Redis 锁就结束,需要设计执行记录和恢复。

实验报告

  • 顺序重复只创建一次
  • 并发重复只创建一次
  • 能解释唯一约束为什么必要
  • 能列出进程崩溃的失败窗口