Skip to content

feat(multi-review): 添加全局 session 清理兜底#115

Open
Svtter wants to merge 1 commit into
mainfrom
global-cleanup
Open

feat(multi-review): 添加全局 session 清理兜底#115
Svtter wants to merge 1 commit into
mainfrom
global-cleanup

Conversation

@Svtter
Copy link
Copy Markdown
Collaborator

@Svtter Svtter commented May 25, 2026

在 orchestrator.ts 中维护模块级 activeSessions Set,跟踪所有存活 session。index.ts 中:

  1. finally 块中先调用 cleanupAllSessions() 再 server.close(),防止单条 finally 被跳过时的泄漏
  2. 注册 SIGTERM/SIGINT 信号处理器,在 runner kill 进程时尽力清理残留 session

作为之前 per-session finally 修复的第二道防线。

Add a module-level activeSessions Set in orchestrator.ts to track all
live sessions. Expose cleanupAllSessions() to delete any sessions that
are still in the set.

In index.ts:
- Call cleanupAllSessions() in the finally block before server.close()
  to ensure no session leaks even if individual finally blocks were
  skipped (e.g. unhandled rejection before reaching them).
- Register SIGTERM/SIGINT handlers for best-effort graceful cleanup
  when the runner kills the process (e.g. GitHub Actions timeout).

This provides a second line of defense on top of per-session finally
blocks added in the previous fix.
@github-actions
Copy link
Copy Markdown

无遗漏

PR 标题和 body 描述的三个要求均已完整实现:

要求 状态 位置
模块级 activeSessions Set 跟踪所有存活 session ✅ 已实现 orchestrator.ts:4, runParallelReviewers (L65/L95) 和 runCoordinator (L124/L150) 中 add/delete
finally 块中先调用 cleanupAllSessions()server.close() ✅ 已实现 index.ts:99-100
SIGTERM/SIGINT 信号处理器 ✅ 已实现 index.ts:45-56

所有 session 创建路径(runParallelReviewersrunCoordinator)都已纳入 activeSessions 追踪,cleanupAllSessions 正确导出并在两处(正常 finally + 信号处理)调用,作为 per-session finally 的第二道防线。无遗漏。

New%20session%20-%202026-05-25T04%3A05%3A42.990Z
opencode session  |  github run

@github-actions
Copy link
Copy Markdown

评审综合报告

最终决策:可合并

四位 reviewer 均无阻塞项,代码整体质量合格。所有发现的改进点均为建议性质。

阻塞项:无

建议项:

  1. activeSessions 全局可变状态(已确认 - quality, architecture)— 模块级 activeSessions 导致测试间状态残留、无法多实例运行,建议封装为可注入实例或通过参数传递。

  2. 冗余的外层 finally 清理(已确认 - performance, architecture)— index.tsfinally 块与 signal handler 均调用 cleanupAllSessions,正常路径下 session 已在各自 finally 中被删除,外层清理为空循环,建议仅在 signal handler 中保留紧急清理。

  3. cleanupAllSessions 串行删除(performance)— for...of + await 逐个删除,session 多时延迟累积,建议改用 Promise.all 并行发起。

  4. Set 并发修改风险(performance)— cleanupAllSessions 遍历 activeSessions 时可能与其他 delete 操作并发,建议遍历前先快照 Array.from(activeSessions)

  5. 多次 Ctrl+C 静默忽略(quality)— process.once 使第二次信号被忽略,清理耗时较长时用户无法强制退出,可考虑超时兜底。


📋 各 Reviewer 详细审查结果
quality

可合并

该 PR 为 multi-review 工具增加了 graceful shutdown 支持,通过追踪活跃 session 并在收到 SIGTERM/SIGINT 时进行清理。

实现正确,错误处理完善(所有删除操作都包裹在 try-catch 中并忽略错误)。信号处理中使用 process.once 防止重复触发,退出码(SIGTERM→143, SIGINT→130)也符合约定。cleanupAllSessions 在信号处理和正常 finally 块中都被调用,能覆盖所有退出路径。

阻塞项:无

建议项:

  • 模块级 activeSessions 是可变全局状态,在单元测试中需要手动清理,建议考虑将其封装为可注入的实例(非阻塞,现有 CLI 场景下可接受)
  • 多次快速 Ctrl+C 时第二次信号会被静默忽略(process.once 行为),用户无法强制退出直到 cleanup 完成,这在 session 清理耗时较长时可能影响体验
security

安全无虞

该 PR 仅添加了优雅关闭的信号处理逻辑和活跃会话追踪,不涉及任何用户输入处理、认证授权变更或敏感数据暴露。会话 ID 来自 API 响应(服务端生成),不存在注入风险。改动范围有限且无安全影响。

阻塞项:无
建议项:无

performance

性能有疑虑

该 PR 添加了优雅关闭的 session 清理机制,核心逻辑无严重性能问题,但存在以下非关键性改进空间。

阻塞项:无

建议项:

  1. cleanupAllSessions 串行删除:使用 for...of + await 逐个调用 API 删除 session。若活跃 session 数量较多(例如大批量并行 review),清理期间会因网络往返累积显著延迟。建议改用 Promise.all(Array.from(activeSessions).map(id => ...)) 并行发起删除请求,以 O(1) 延迟完成清理。
  2. Set 并发修改风险cleanupAllSessions 遍历 activeSessions 时,信号处理程序与并发 reviewer 的 finally 块可能同时对该 Set 执行 delete。JavaScript Set 在遍历期间被修改的行为虽不会崩溃但结果不确定(可能遗漏项或遍历到已删项)。考虑在遍历前快照:const ids = Array.from(activeSessions) 后再迭代删除,或者加锁保护。
  3. 冗余的 finally 清理mainfinally 块调用 cleanupAllSessions,但每个 reviewer 和 coordinator 各自的 finally 已确保 session 被删除并移出集合。正常路径下 activeSessions 始终为空,使得外层清理是空循环。虽非性能问题,但属于不必要的 I/O 路径,建议评估是否可移除。
architecture

架构有疑虑

该 PR 为 multi-review 模块添加了信号处理优雅关闭机制,整体改动集中在 index.ts(入口层)和 orchestrator.ts(编排层),定位合理。但存在一处非阻塞的架构疑虑。

阻塞项:无

建议项:

  1. orchestrator.tsactiveSessions 是模块级可变全局状态(mutable module-level singleton),会引入隐式耦合:测试间状态残留、无法同时运行多个实例。建议改为通过参数或上下文对象传递 session 跟踪信息,或将 orchestrator 封装为可实例化的类,使 session 生命周期与实例绑定。
  2. index.tsfinally 块和 signal handler 中都调用了 cleanupAllSessions(client),存在语义重复:正常流程下 session 已在各自的 finally 中被删除,主 finally 中再遍历一次集合通常是空操作。可考虑只在 signal handler 中做紧急清理,主流程靠已有 finally 足矣,降低代码冗余。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant