跳到正文
FunCoding

搜索

搜索文档、Skill 和 MCP

Bridge 回收与恢复边界

避免关闭竞态,理解恢复超时、隔离新会话和有界 replay。

Bridge 生命周期既管理逻辑 session,也管理共享的 workspace ACP child。关闭最后一个 session 不一定立即等于所有工作区活动结束。

回收 child 的前提

Session、restore、workspace control、discovery、authentication 和 runtime operation 全部排空,且没有显式 ensure keepalive 窗口时,未设或为零的 channelIdleTimeoutMs 可立即回收 child。

单纯 preheat 保留到首次使用,不会仅因首次状态读取就触发立即回收。正 idle timeout 或有效 keepalive 可以延迟回收,采用剩余时间更长的一项。

受信主工作区为兼容会尝试预热;受信 secondary 在首次 runtime command/session 使用时启动,未信任 secondary 不启动 ACP。主工作区的历史兼容路径不能直接外推到 secondary。

isDying 与保留引用

任何 teardown 都必须在 await channel.kill() 前同步设置 isDying=true。这样并发 ensureChannel 不会附加到即将退出的 child,而能选择新的 channel。

设置 isDying 后仍保留 ChannelInfo,直到 channel.exited。否则第二次退出信号的 killAllSync 找不到还在宽限窗口内的旧 child,可能遗留进程。

恢复超时不是请求取消

sessionRestoreTimeoutMs 默认 60000ms;显式 initialize timeout 可将其提高,但不会降低默认恢复期限。当前 ACP SDK 的 load/resume 超时不能取消底层请求。

因此超时后仍保留结算约束与容量占用,直到真实请求结束或 transport 关闭。迟到成功结果只关闭一次且不登记为可用 session;不能因为 HTTP 已返回超时就立即释放全部名额或重复恢复同一 ID。

清理结果不确定时,只隔离该 workspace 的新 session 工作;已有 session 与 workspace control 仍可继续,直到 channel 排空并重建。隔离并非整个 daemon 已不可用。

replay 与完整历史

BridgeRestoredSession 可包含 compactedReplay、liveJournal 和 lastEventId。它们都是有界内存窗口,不是磁盘完整 transcript。

内部选项默认与限制
compactedReplayMaxBytes默认 4 MiB,硬上限 256 MiB
maxJournalEvents默认 10000 个 replay entries
maxJournalBytes默认 8 MiB 序列化 source events
每个合并文本或思考 entry最多合并 256 个兼容 source events

事件类型与归因边界仍保留。历史窗口裁剪后以无 id 的 history_truncated 标记开始;live journal 裁剪标记带 scope:live_journal。标记中的 retained/truncated 数量统计 source events,不是合并后的 entry 数。

完整持久记录需走transcript 接口。新客户端应检测稳定 session_resume capability;unstable_session_resume 只是保留的旧别名。

其他有限资源

eventRingSize 的内部软上限为 1000000,超过时构造失败,目的是拦截明显错误配置,不表示上限值可安全用于所有 session 数量。

审批等待默认无限:permissionResponseTimeoutMs=0;每 session 默认最多 64 个待审批请求,超出会取消并警告。MCP restart 的 bridge 期限为 300000ms,以覆盖长 discovery;客户端不应随意使用远短于服务端操作的期限后盲目重试。

关闭 bridge 时先将待审批按 session_closed 取消,再关闭 child。退出和释放所有权的顺序见Serve 生命周期。