Repository navigation
fix(chat): avoid holding source routes during recovery provider reads - #7525
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
There was a problem hiding this comment.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
动机 / Motivation
原 Chat 在检查历史失败时,用户的新输入和状态查询也会被同源的慢消息读取阻挡。原消息读取等待两秒时,旧路径把新状态请求一起拖住;修复后新输入可先受理,旧恢复若已过时则保留原请求。隔离真实入口的三组对照中,新输入从约2.1秒降为66–75毫秒,旧失败字节不变且没有模型启动。此改动不认证自然故障全部恢复、账号切换、完整双端同步或全部历史业务完成。生产安装采用与持续锁指标、真实原业务和各自最终回传仍需分别核验。
改动思路 / Approach
远端读取属于既有 Python provider IO,恢复资格仍由原 TypeScript owner 判定;局部重排无需新状态或执行器。本 PR 只交付原恢复路径的读取与共享路由锁隔离,以及忙路由下保留请求后重新核验。继续只把 provider IO 放在 Python 适配层;当前 binding、canonical Session/Turn 和 source 请求快照仍在既有 typed owner 与原路由 fence 下决定是否准入。路由忙时不是成功或拒绝业务,而是原 journal 不变、既有 worker 下次重新读源。这个边界能独立交付并回退,无需新 scheduler、cache 或消费者。单纯扩大超时仍阻挡新输入,直接去锁会失去序列化,两者均不如当前修复。
| 同一合成负载 | base | 当前 head |
|---|---|---|
| 原消息读取延迟2秒时,新状态请求准入 | 2.098–2.118秒 | 0.066–0.075秒 |
| 旧失败字节与新模型启动 | 字节保持;0次 | 字节保持;0次 |
这里用表格解释变化,没有另画或声称验证过渲染图。测量属于隔离真实 File/stdio/TS 入口与合成 provider,不是生产 p95。
具体改动 / Changes
关键代码讲解
ChatExternalConversations.recover_failed_request(loopx/capabilities/native_chat/external_conversations.py:120)仍先持有本请求锁,读原 Turn 与 native 完整证据,随后在共享 source 路由锁外读取当前渠道身份及原消息。它使用现有 try_exclusive_file_lock;若其他路由正在持有,原请求直接保持不变。成功取锁后,当前绑定必须逐值等于实际观察的绑定,再调用既有 _resolve_observed。原 Session、Turn 与完整同源请求快照还要一致;新输入可以先准入,过时的旧恢复不会覆盖它。已准入 receipt 的例外仍交原 TS 分支准确采用,不重新执行业务。
ChatExternalConversations._context_recovery_plan(loopx/capabilities/native_chat/external_conversations.py:49)新增的 selected_binding 只在本次调用中传递已经完成 typed 验证的绑定,避免在 source fence 内再做一次 provider 读取。普通及 discovery 调用仍沿原分支;候选、unknown、read-only review、unfinished work 和资格判断仍来自原 collaboration.conversation.request,没有新增 Python 决策 owner。生产 +22/-7 行,另76行测试覆盖 status、correction、revoked、source-changed、unknown、unchanged 和 route-busy 后再次推进。
规范:docs/reference/protocols/manager-evidence-and-continuity-v0.md,不可变 revision f63647e2e867a30dd8761baaa1df69cba9c9860b。MC-1 对应 Core 状态与资格 owner 保留;MC-2 对应原来源、绑定/授权、空闲与纠正/停止重检;MC-3 对应原 worker/原 transport 和回执恢复,未把准入等同业务完成。三项均按本修复边界 implemented;整体 App、账号和自然生产验收没有在此结清。
对主干的风险 / Risks
最强反例是 source 读取期间已撤权或新纠正到达,却用旧观察准入。精确绑定比较、同一 typed resolver、canonical 快照和原 TS 资格共同防止这种误执行;新的 source 延迟用例补上了仅延迟 native RPC 的旧测试盲点。忙路由会等到既有 worker 的下一次自然访问,这是明确的安全延迟;用例同时检查忙时不写 reservation 和释放后以新源证明推进。没有增加重试引擎、账号操作或消费者。
PASS:14项聚焦;扩大原 worker/路由/unfinished-work/绑定/回传/feedback 套件 457 passed in 545.49s (0:09:05);Ruff、编译、4项 direct checks、2项 catalog premerge 均通过。FAIL 作为回归证据保留:相同新 status/route-busy 测试在精确 base 失败,三次 base 协议对照均不满足独立响应性 oracle。Speedscope 主线程捕获成功,只说明读源等待仍存在,不能把堆栈权重相加当耗时或业务收益。初次头样本与扩大套件重叠,原记录保留但不用于受控性能结论;以上数字来自验证停止后的顺序重测,安装版另为0.072–0.088秒。当前 Goal 的 change-quality policy 为 disabled;按 managed review 配置没有查询、轮询或等待 CI。
语义与 CI 对齐
本改动复用现有 typed vocabulary 与 provider IO,不添加状态协议、角色或权限。默认行为变化已在 PR 与测试明确:busy recovery 从等待变为保留 journal 后重新核验,普通 intake 的锁和授权不变。原三次尝试、backoff、未知效果与精确已准入回执合同保留。没有通过提高 timeout、删失败断言或声称 backend 迁移来规避问题。
我的整体评价 / Verdict
未发现阻塞本精确头的缺陷。long_horizon 与 user_experience 在这个已复现边界上 improved:新输入不用为旧读源再手工确认/重试,旧恢复只在当前证明仍有效时推进。已检查两文件完整 diff:只改既有 Python 恢复 IO 与合成测试,没有渲染、消息文案、布局或导航变化。本评审未将浏览器或原生 App 完整同步、生产持续延迟和自然业务完成计为通过。兼容性保留的是已有持久 journal/失败及 receipt,不是并行新旧决策代码;生产只复用原 owner,比例合适。远端读取属于既有 Python provider IO,恢复资格仍由原 TypeScript owner 判定;局部重排无需新状态或执行器。本 PR 只交付原恢复路径的读取与共享路由锁隔离,以及忙路由下保留请求后重新核验。生产安装采用与持续锁指标、真实原业务和各自最终回传仍需分别核验。这个有用增量可以评审合入,安装采用与持续生产闭环继续由原维护责任核验。
English verdict: APPROVE — cc70b352a4c2777c5535a6a503d8f97a12d4fcc8 removes provider-read source-route blocking while preserving typed authority, original receipts and unknown-effect safety; focused, real-protocol and repository-native checks passed.
恢复旧请求时,渠道身份及原消息读取仍会持有共享 source 路由锁;慢读取会阻挡同一会话的新输入。此修复将这些只读调用移到路由锁外,取得锁后再用当前 binding、既有 typed owner 和 canonical Session/Turn/请求快照核验。路由正忙时保留原请求,让既有 worker 下次重新读取,避免等待后采用旧观察;同请求锁、已准入回执采用及原队列继续保留。
这是现有 Chat/Lark 恢复入口的 IO 边界修复,未增加消费者、配置、权限或重放策略。延迟恢复、unknown 和后续输入仍不能授权重执行业务;完整双端同步及自然故障恢复仍需独立验收。
Validation:
顺序重测在扩大套件结束后执行,安装版对应输入耗时0.072–0.088秒。初次头样本曾与扩大套件并行,记录保留但不作为受控性能结论;未改超时或断言。