Files
AgentLab/backend/tests
ThearchyHelios ed83aa2fa4 并行支路一条失败时,运行不再永久卡在 running
两条并行支路一条失败,LangGraph 会取消另一条;那一条若正在写库(节点收尾写
工件最常见),整个运行就可能永远停在 running,占着的并发名额也不还。修审批时
加的并行驳回用例约五次卡一次,才把它翻出来。

根因在两层,都是"取消打进进行中的数据库清理":

1. aiosqlite 0.22 的 stop() 每调一次都往工作线程队列里放一个"关闭并退出"
   请求,线程处理完第一个就退出,之后的请求没人处理,等它的一方永远挂着。
   close() 的 finally 会调 stop(),SQLAlchemy 优雅关闭被取消后退回的强制
   terminate 也会直接调——同一连接上两者一碰就卡死。并发 close 两次,10 次卡
   10 次。现在同一条连接的 stop() 只真正执行一次,之后的调用拿同一个 future。

2. 卡死解开后露出第二层:SQLAlchemy 的 _close_connection 记完日志会把
   CancelledError 原样抛出,跳过了把连接记录清空的那一行,已经关掉的连接留在
   池里,下一个取到它的人拿到 "no active connection"。主引擎开 pool_pre_ping:
   探活失败按断开处理、换新连接(aiosqlite 方言把这句判为断开,已核对源码)。

验证:test_aiosqlite_close.py 4 例是确定性的(并发 close、close 撞上强制
stop、被取消后的 close、重复 close),去掉补丁 3 例超时失败。复现脚本同一场景
连跑两批各 40 轮:修前 12 轮内必卡,修后 80 轮 0 卡、0 次坏连接抛给调用方;
SQLAlchemy 在被取消时仍会记一条"Exception terminating connection"日志,那是
它自愈过程的记录,不影响结果。334 → 338 passed。
2026-09-25 15:20:46 +08:00
..