Repository navigation
fix(lark): prioritize current replies over historical recovery probes - #8143
Conversation
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
loopx-agent
left a comment
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
通过飞书等待原助手答复的用户,会遇到正文已经生成、却排在历史恢复任务之后的情况。 当四个投递位已满,新正文到达后,旧实现让下一批尚未尝试的历史恢复继续占位;新实现先取当前正文。 当前正文能获得下一个可用投递位,同类任务仍按尝试次数公平选择。 本 PR 不新增消费者、重跑业务或把投递排序当成已送达。 已运行任务的耗时、完整历史恢复及安装后的真实渠道读回仍须分别验收。
改动思路 / Approach
在现有四位投递池中使用传输层的当前状态提示,比新增队列、扩池或取消旧任务更直接,也不移动任何授权和发送权威。 本 PR 只修改当前正文与历史恢复之间的取位顺序,并保留原服务、单项回传锁和现有尝试记录。
这里的历史恢复指已经发过一份通知、仍需原生结果核对的旧请求;当前正文指尚未发出的消息或 App 回传。二者都保留在原持久记录中。调度器先按这一传输提示区分,再按已有尝试次数选择;原池满载时不会额外排入内存队列,已运行任务也不会被中断。下一空位更快用于正文,但正文内部仍保持原消息顺序,真正发送仍由原来的校验路径负责。
具体改动 / Changes
依据 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,规范版本 5275c5b7bda9df30bcd9f9e3bdcff5e3e75ebf24:Reply-pool 保留原四位投递池;App-projection 保留每次发送前的 Session、绑定、受众和原消息核验;Unknown-attempt 保留未知效果不盲重发。三项均由现有入口和原回传路径承接,新增排序本身没有签发执行或发送权限。
关键代码讲解
LarkGoalTopicRuntimeService._reconcile_private在旧公平性键前增加恢复提示。即使正文在满池时才出现,它仍保留在未提交发现集合中,下次有空位先于旧探测被选择。原先的容量、停止、Future 回收和辅助任务预留没有改写。LarkPrivateConversations.is_recovery_path从已有结构化状态和 App outbox 位置推导提示,不新增持久字段,也不根据正文关键词判断业务是否完成。提示只改变先后,后续reconcile_request继续重新读取原权威。test_current_body_uses_next_slot_before_unattempted_recovery_backlog使用真实线程池、原扫描循环和文件记录,让第一波占满后再加入正文,断言下一波包含它。四种来源与容量组合在不可变 base 上全部失败,在本 head 上通过;测试还等候真实 Future 收尾,避免把线程检查点误当成工作完成。
对主干的风险 / Risks
最主要的取舍是:持续不断的正文流量可能继续推迟低优先的历史恢复;排序没有取消旧项,同类尝试公平性和空位恢复仍保留。本 PR 也不保证四个已经卡住的任务会被立即释放,原生/网络耗时仍需原服务单独照看。用新增消费者或扩池掩盖这个等待,会引入重复效果风险,本实现没有增加这些机制。
PASS:聚焦调度/恢复验证 9 passed, 360 deselected in 2.62s;原来源、撤销、保留尝试、慢 reaction 与已完成答案的控制 7 passed, 362 deselected in 33.73s;同一新反证在 base 为 4 failed in 22.50s(预期失败)。最终标准 premerge 通过 6 项 direct checks 和 10 项选择检查,没有阻塞失败。interaction_contract._admitted_interaction_next_cli_actions 的原复杂度问题在 base 独立复现,native gate 仍列 inherited advisory,未修改预算或隐藏错误。
语义与 CI 对齐
这是传输 IO 的默认取位顺序修复,已在 PR、注释和回归名称中明确披露。它复用现有 delivered 状态;没有新增共享 vocabulary、Goal 配额、授权 gate 或业务重试。现有来源撤销与未知效果控制继续通过。当前 Goal 配置不查询或等待 CI,本次未抓取 CI 状态;本地检查和真实原渠道验收各自保留边界。
我的整体评价 / Verdict
本次为 justified_increment / APPROVE。在现有四位投递池中使用传输层的当前状态提示,比新增队列、扩池或取消旧任务更直接,也不移动任何授权和发送权威。 本 PR 只修改当前正文与历史恢复之间的取位顺序,并保留原服务、单项回传锁和现有尝试记录。 long_horizon 是有依据的取舍:优先缓解未读正文,保留历史恢复但不承诺它在持续正文流量下的固定时限。user_experience 在本源码边界改善,不增加用户导航、重输或确认。已检查原投递路径,本改动不涉及可视布局或内容排版,视觉检查不适用;安装后的渠道延迟和实际完整回传仍是独立验收范围,不能由这些 fixture 宣称用户已经收到。
English verdict: APPROVE the current-body scheduling repair at d14e516; original-source guards and bounded capacity are retained, while installed delivery needs independent readback.
Unsent private Chat bodies can wait behind a large historical recovery backlog because every never-attempted path has the same fairness count. Give current Lark bodies and App mirrors the next available slot ahead of historical recovery probes, while keeping attempt fairness within each class and the same four-worker pool.
The distinction is a local transport scheduling hint. Reconciliation still reads the original source, current grant and frozen provider attempt; no request is replayed, new consumer started or delivery marked successful by the hint.
Validation: nine focused scheduler/recovery cases passed. The same four new full-pool cases fail against the unchanged base because the new body loses the next released slot to another untouched historical probe. Existing backlog fairness, backoff, bounded-capacity and scanner-recovery controls passed. Installed original-conversation delivery remains a separate acceptance step.