-
sessions.size 在此之前没有任何人过问。一次心跳泄漏就攒到过 82 个进程 / 17.5 GB(约 215MB/个),而批 4 刚把公司级并行放开(单公司上限 20)—— 机器上同时能起多少完全没有闸门,正是最容易失控的时刻。 AGENT_MAX_SESSIONS,缺省 12,**调用时读不是模块加载时快照**(快照一次就 意味着改配置要重启才生效,而且不报错 —— company-paths.js 顶上那条教训)。 非法值(0/负数/非整数)回落缺省,不当成无限。 满了怎么办:**回收最久没用的空闲会话,而不是直接拒绝**。session 是可复用的 池化资源,杀掉一个空闲的只是让它下次冷启动几秒;拒绝会让一个本来能跑的任务 因为资源原因失败 —— 那是把可恢复的代价换成不可恢复的。 只有一个空闲的都没有(全部在途)时才抛 SessionPoolFullError。刻意抛而不是 静默放行 —— 静默超出正是这个仓库栽过的那一类「超出去但不报错」。 两个实现细节: - 腾位置发生在 createConnection **之前**:起完再判等于该拦的那个已经起来了 - 空闲态用显式的 idleSince 时间戳记,不去戳 IdleTimer 的私有 _timer; getOrCreate 复用时清空它(在途 = 不可被挑走) - _evictForRoom 故意不 await reset():腾位置只需要把它从 Map 摘掉, 子进程收尾可以后台走完;await 的话一次腾位要串行等一次进程退出 守卫:server/tests/unit/session-pool-max.test.js(5 例,不起真进程, 只验判据本身:挑最久空闲的、在途的不许动、全在途就抛、没满不动、非法配置回落) 全量:129 文件 / 1245 测试全绿。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>