Repository navigation
fix(lark): keep admissions moving during background stop - #6685
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). This is an author-side model review, not a human or independent-person approval. Exact head: f296119190252b9350eafd83512559e28cd36f01. 未发现阻塞项;最强剩余缺口是安装后真实 SDK、飞书及网页时限。
动机
已在飞书话题或本人私聊发出停止指令、随后还要继续工作的用户。
旧版在查询旧后台命令时占住消息入口及话题路由锁,后续消息与重复停止都可能等待;新版先固定原停止目标,再由现有回复工作池处理原生控制,使后续消息先进入持久队列。
已验证的改善是原生清单 RPC 被阻塞期间,后续规范 Turn 仍能持久受理;释放适配器锁后它开始原生执行并存活,原停止效果和答复保持一次。
本次不改原生适配器互斥锁、不新增消费者或队列、不承诺已达到五秒停止/网页时限,也不宣告完整社区准出。
安装后的真实 SDK、飞书回执与整页时延尚未由本 PR 的合成协议回归证明;完整社区用例和三轮关键验收仍由既有交付任务继续承担。
改动思路
停止目标的正确性属于既有 Core 不变量,原生控制属于现有工作池的 IO;把 IO 留在话题路由锁内既非授权所需,也会阻止已经获准的新工作持久受理。
当前 PR 完整交付默认 Lark 入口的“固定原目标后释放受理”及其恢复兼容;安装采用和真实端到端时限沿既有社区验收继续,不新建另一套调度或完成状态。
先保留当前源消息、授权和规范目标的决策,再拆开 IO 阶段。请求锁先于话题路由锁取得,重复停止等待自己的请求时不占住后续消息的路由。原 listener 在 Core 固定原目标后返回;原回复工作池恢复同一请求,没有新建第二个消息消费者。传输层继续使用既有 captured 格式,并以 request_ref、binding_id 和完整 source 对齐 Core;成功回传仍走原 Inbox 的独立来源核验。
下表依据 f296119190252b9350eafd83512559e28cd36f01 的源代码描述锁寿命,不代替执行证据:
| 触发与阶段 | 旧版 | 此版本 |
|---|---|---|
| 旧后台命令清单慢 | 入站和话题路由等原生 IO | 原目标落盘后,回复池执行 IO |
| 重复停止等待 | 可能占着话题路由锁 | 只等原请求锁 |
| 后续规范请求 | 可能被旧控制阻塞 | 已验证在清单 RPC 内阻塞时仍持久受理 |
| 原生执行与最终回执 | 适配器串行,控制后回传 | 仍串行;控制与来源核验成功后才回传 |
具体改动
生产代码三处 +92/-42,现有测试文件 +204,两个 RFC 镜像 +14。没有生成文件、私密信息、新 CLI、队列、持久状态或用户权限。测试门设在真实 native RPC 写入边界,适配器互斥锁仍被持有;断言的是已落盘受理。释放后才等待上游执行,核验新执行存活、旧归属子进程退出、无归属子进程保留和原停止回执/效果恰好一次。
关键代码讲解
ChatExternalConversations.admit:接收原请求,按请求锁→路由锁核验当前授权,持久固定目标;离开路由锁后才执行旧后台 IO。精确重放仍核对原内容,未记录原范围的旧请求不借当前工作重建意图。_finish_background_stop:只读取固定候选的原生存活子集,再调用既有类型化响应投影与确切中断 owner。它不改已完成答案,不扩大候选;原生错误保留原请求供恢复。LarkPrivateConversations.admit:既有源消息及 App 核验后调用 Core;延后控制时仍持久写 captured,回滚读者无需认识新状态。该参数只表示调度,没有授权意义。reconcile_request:恢复前核对原 request/binding/source 三元关系,Core 完成后复制既有 response_code 等结果字段;仍 prepared 时保持未确认,缺失或不匹配走旧完整受理路径。最终投递继续重新核验实际来源。_poll_profile:把现有 callback 绑定为延后旧后台控制,使用现有回复池。活跃 Turn 的确切停止不等历史清单;原生执行本身仍受已有适配器互斥锁保护。
规范依据是 docs/architecture/rfcs/app-conversation-and-async-inbox-v0.md,接受的变更前版本 c9c3adf63f9771ef95f1fcca12b11ed7de1f69eb,107–135 行。下面的标识是无编号条款的描述标签:
| criterion_id | 处置和证据 |
|---|---|
| original-source-and-thread | implemented:原 App/消息/root/授权检查及原话题投递不变,相关负面回归通过。 |
| freeze-before-native-inventory | implemented:Core 在原生 IO 前固定原候选;最终 RPC 内阻塞、写盘中断和重启回归验证。 |
| unknown-and-closed-original | implemented:未知旧目标与已关闭原 Session 保持未确认;既有 legacy/new_session 负例通过。 |
| active-stop-and-once-only-effects | implemented:活跃停止在 base/head 均通过;新执行和无归属子进程存活,原停止效果及 terminal ledger 不重放。 |
| separate-installed-and-community-exits | deferred:真实安装、SDK/飞书/网页五秒时限、完整社区包及三轮关键验收由既有交付任务继续,本源审查不宣告完成。 |
RFC 新增段落只说明默认 IO 时序,不把实现新增的描述反过来当作独立验收依据。
对主干的风险
最危险的误判是把“路由锁释放”当作“上游执行并发”。早期测试门在查询 helper 入口前;这不能证明适配器锁持有期间的行为。最终门已移入 thread/backgroundTerminals/list 的实际 RPC 写边界,只要求规范 Turn 先持久受理,之后才断言上游执行并存活。新 Turn 合法进展可能增加一条消息,故重复性 oracle 锁定原停止 tuple、terminal ledger 和 terminate 调用,不再错误要求整个写消息列表永远不变。
相同最终 fixture 在固定 base 为 1 failed/1 passed,在 head 为 2 passed;刻意把路由锁放回原生控制时变为 1 failed/1 passed,新受理超时。最终完整改动测试模块 24 passed;之前六模块 257 passed,最终提交只强化测试,五个运行代码/RFC blob 相同,因此复用其余 233 个未变用例。旧安装版本的真实方法读取候选 captured/Core 日志,另有 1 passed,保留后续工作与原回执一次。
实际默认调用链是 Chat 启动→Lark runtime→原 callback→Core,非只增一条不可达测试路径。原生 inventory/terminate、身份失败、写盘中断和重启均保持原目标与未确认状态;关闭原 Session 仍被原生适配器拒绝重开。没有声称 source fixture 能证明生产 SDK、网络回执和整页时延,也未放宽现有 scope/权限或适配器串行边界。
语义与 CI 对齐
采用 reuse_existing:prepared、target_recorded、captured 与既有类型化 stop/响应投影仍只有各自原 owner。语义扫描的动态来源盲点不被当作安全证明。最终 native premerge 的 6 项直接检查和 11 项选中检查通过,包含双语 RFC、架构 ratchet、语义词汇及公开边界检查;Ruff 通过,仓库配置的 mypy 对 17 个文件成功。可选的三文件 strict 检查仍有 13 条与固定 base 同身份同详情的旧错误,没有宣称全局 strict 通过。依据当前 Goal,未拉取、轮询或等待远端 CI。
我的整体评价
APPROVE,交付判断为 justified_increment。long_horizon = improved:后续持久受理与原请求恢复不再相互阻断;user_experience = improved:用户继续使用原停止及后续消息,无额外导航、重新输入已知信息或确认轮次。原生执行与最终答复仍可能等待适配器和外部服务,五秒时限尚未由此源测试证明。
已有停止正确性、原消息核验和旧 captured 读者属于必要兼容;本次没有增加版本分叉或替代状态 owner。较小的“只移到 worker”方案被路由锁变异实证否定,新队列或绕过适配器锁则增加无依据的状态/并发负担。保持现有 owner 的完整小切口有正收益;完整社区准出仍开放。审查结论绑定上述 exact head,若生产逻辑再变,需要重新核验这条受理、原范围、实际效果与一次回执的轨迹。
English verdict: APPROVE this bounded default-listener admission fix. The real native-RPC boundary proves durable admission, not concurrent upstream dispatch or installed latency. Frozen scope, recovery and once-only original effects remain covered; production adoption and full release acceptance stay separate.
|
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max Post-merge audit — new actionable concurrency finding 评审 head: 动机在 Lark 群话题或本人私聊中,用户要求停止已完成答复遗留的后台命令,随后继续补充工作。 改动思路复用现有请求日志、类型化 Core 判定和四个回复 worker 是合适的边界;当前还须消除 canonical 候选扫描对原生 adapter 锁的依赖,不能只把第一条停止请求的 IO 移出路由锁。 原路径在同一个话题路由锁内完成目标选择、原生清单读取和取消;新路径先取得请求锁,再短暂取得话题锁完成原目标冻结,释放话题锁后处理原生 IO。默认 listener 通过
具体改动规范依据是 base 关键代码讲解
原默认同步入口的同输入 base/head 读回完全相同:原 Session、固定目标、完成回执、响应码、一次取消及一次回复均保持。另将候选产生的 对主干的风险[P2] 新停止请求仍会把原生 IO 等待带回入站路由锁第一条停止请求 A 已固定目标,回复 worker 正在 独立反例经默认 listener callback、真实 Core/类型化 bridge 和文件存储运行:无第二请求与原请求重投两个控制组都能在屏障释放前受理 C;新 最小修复:让路由锁内的 canonical 候选冻结不等待原生 adapter IO,复用现有 Core/store 读边界并保留原请求冻结及 effect 前授权检查;补上两个不同消息 ID 的 /stop 与第三条普通消息的并发回归。不要靠全局取消锁、扩大目标或延长超时解决。 语义与 CI 对齐复用既有 当前本地证据:七个相关模块 我的整体评价REQUEST_CHANGES。这个方向能在已有 owner 中交付真实增量:原停止请求的慢 IO 和重投已与普通入站分开,目标和结果回读也保持清楚。长期连续工作的已验证范围包括原请求重放、失败后恢复、后续工作保留及源读取器兼容;不把这些局部证据当成长期运行或真实安装净收益。用户体验目标仍未完全成立:另一条新停止消息会重新堵住入站,用户仍需等待底层控制返回才能继续。 复用现有请求日志、类型化 Core 判定和四个回复 worker 是合适的边界;当前还须消除 canonical 候选扫描对原生 adapter 锁的依赖,不能只把第一条停止请求的 IO 移出路由锁。 English verdict: REQUEST_CHANGES - head f296119. A distinct second /stop waits for the native adapter lock while holding the shared route fence, blocking a later ordinary message. Real Core/File and child-process probes distinguish duplicate replay from a new request; local positive, recovery and compatibility evidence is retained. The bounded canonical-read/IO lock boundary and a three-message regression need repair. |
Completed-turn background cancellation currently runs inside Lark inbound admission and holds the topic route fence through native inventory and interruption. A later message or duplicate stop can therefore wait even after the original targets have been durably fixed.
Freeze the existing Core request under its source fence, then let the existing reply workers perform native control while holding only that original request fence. Duplicate waiters take their request fence before the topic fence. The transport retains its existing
capturedrecovery format; rollback readers can finish the same request. Active-Turn interruption, fresh authority/source checks, frozen targets and verified once-only replies stay with their existing owners.Validation at f296119:
This source slice does not certify installed five-second stop/web timing or the full community release pack. No new queue, consumer, persistent status, user setting or permission is introduced.