已关闭
[Bug]: DB 写失败时 write 异常未处理,cache 被脏刷新 #112
Vxiaomao52创建于 7月17日关闭于 7月29日
openJiuwen-bot
7月17日 评论:
7月17日 评论:
欢迎来到 openJiuwen 社区
Hey @Vxiaomao52 , 感谢你对社区的贡献.
机器人使用手册
有关指令的使用,可以点击 此处 查看详情。开发人员可以在每个PR或Issue下方评论特定指令来触发机器人任务。


7月29日 issue状态由 TODO 改变为 DONE
7月29日 关闭了 issue
Vxiaomao52
7月29日 评论:
7月29日 评论:
回归结果
6 passed in 0.66s
| 用例 | 场景 | 预期 | 实际 | 结果 |
|---|---|---|---|---|
| REG-001a | create 抛 OperationalError(DB 连接拒绝) |
异常传播,cache 不刷新 | 异常传播,cache.set_calls=0 | ✅ |
| REG-001b | create 抛 RuntimeError(DB 完全宕机) |
异常传播,cache 不刷新 | 异常传播,cache.set_calls=0 | ✅ |
| REG-002 | create 抛 IntegrityError + get 返回 None |
RuntimeError 传播,cache 不刷新 | RuntimeError("record not found"),cache.set_calls=0 | ✅ |
| REG-003 | create 抛 IntegrityError → 正常回退 update |
upsert 成功,version 自增,cache 刷新 | version=2,cache.set_calls=2 | ✅ |
| REG-004 | create 静默返回 None(残留风险) |
标记已知残留 | cache.set_calls=1(符合预期标记) | ✅ |
| REG-005 | DB 正常写入(基线对照) | DB + cache 双写成功 | 数据一致,version=1 | ✅ |
修复验证结论
原始缺陷路径:except Exception 吞所有异常 → 脏缓存。修复后 except IntegrityError 仅捕获主键冲突:
- DB 宕机(OperationalError / RuntimeError):异常正确传播至调用方,
CacheBackedDataStore.write在 line 42 处即抛出,不执行 line 52cache.set_json→ 脏缓存阻断 ✅ - 主键冲突 + DB 不可用(IntegrityError + get=None):
existing is None触发RuntimeError("record not found for update")→ 异常传播 → 脏缓存阻断 ✅ - 正常 upsert(IntegrityError + get 成功 + update 成功):回退路径正常工作,version 自增 → 业务正常 ✅


7月29日 issue状态由 DONE 改变为 CLOSED
Checklist
🐞 问题详细描述
DB 完全宕机时
DbDataStore.write吞掉 create 异常,write 不向外抛,CacheBackedDataStore继续刷新 Redis,出现"DB 未写入但 Redis 被刷新"的脏缓存。根因
DbDataStore.write(db_data_store.py:105-136)的设计意图是"先 create,主键冲突则回退 update",用try/except Exception包裹 create。但except分支吞掉所有异常(包括非主键冲突的 DB 宕机异常),无条件走 get+update 回退路径。当 DB 完全宕机时:RuntimeError("DB down")→ 被except Exception捕获(line 120)CacheBackedDataStore.write(cache_backed_data_store.py:42-52)继续执行cache.set_json,Redis 被刷新触发条件
runtime_db_enabled=True影响范围
代码位置
except Exception as e: logger.debug(...)← 吞异常过宽await self._db.write(...)后无条件执行 line 52cache.set_json复现证据(TC-R01)
self.db_handler.create = _always_fail_create # create 永远抛 self.db_handler.get = _always_return_none_get self.db_handler.update = _always_return_none_update await self.adapter.put("conv-r1", {"v": 1}) # 不抛 self.assertNotIn(("session_task", "conv-r1"), self.db_handler._store) # DB 无记录 self.assertEqual(len(self.cache.set_calls), 1) # cache 被刷新 ← 脏刷新修复建议
if update 返回 None 且 get 返回 None: raise RuntimeError("DB write failed: record not created")CacheBackedDataStore.write可增加db.write返回值校验,确保 DB 写入成功后才刷 cache详细的环境信息描述
单机环境本地部署
其他辅助信息
代码片段,agent-runtime\applications\a2a_service\common\db_data_store.py
版本信息
感谢您的贡献 🎉!