Skip to content

控制面优雅停机、带库连通的健康检查、单实例锁 - #85

Merged
joesmart merged 1 commit into
mainfrom
joesmart/ops-shutdown-health
Oct 23, 2026
Merged

joesmart merged 1 commit into
mainfrom
joesmart/ops-shutdown-health

Conversation

@joesmart

Copy link
Copy Markdown
Contributor

改了什么

  • main.ts 注册 SIGTERM、SIGINT,调 server.close()。走完以 0 退出;8 秒没走完,或者停机中又收到一次信号,以 1 强退。unhandledRejection、uncaughtException 先记日志,再走同一套停机,以 1 退出。
  • 新增 GET /api/health,不用登录。库连得上回 200 {"ok":true};库连不上回 503 连不上数据库;停机开始后(AgentHub.closing)回 503 控制面正在停机。控制面在 main 上本来没有这条路由,Web 的 mock 和 Playwright 用的是 mock 里的同名路由。
  • 新增 instance-lock.ts。启动时先用一条专用连接拿会话级 pg_try_advisory_lock,拿不到就报「同一个库上已经有一个控制面在跑」,以 1 退出。这时还没开始监听,也还没执行 startServer 里把在线电脑写成休眠的那一步。持锁连接断了也按停机流程以 1 退出。这条连接关掉了 max_lifetime,因为 postgres.js 默认 30 到 60 分钟轮换连接,会话锁会跟着丢。
  • deploy/README.md 新增「单实例、停机和探活」一节,docs/开发.md 补一句:多个工作树要各用各的库。

为什么

  • 控制面缺少优雅停机和健康检查 #24:main 上没有信号处理。容器里 node 是 PID 1,PID 1 没有处理器时 SIGTERM 会被直接忽略,所以现在是 docker 先等 10 秒再 SIGKILL,AgentHub.closing 立不起来,「标记留给重启」的路径走不到。
  • 控制面隐含只能单实例运行,但没有守卫也没写进部署文档 #25:回合计数、电脑连接表、画面中继、补扫都在进程内存里,起第二个实例会丢推送和派活。
  • advisory lock 按库隔离。控制面测试每个文件一个随机库,互不阻挡;e2e 在进程内调 startServer,不经过 main.ts。pnpm dev 下 tsx watch 会等旧进程退出再起新的,热重载也不会和锁冲突。

怎么验证的

新增 test/process.test.ts(真起 src/main.ts 子进程,共 6 条)和 test/health.test.ts(2 条):

  • SIGTERM:在线电脑收到 1012,库里转休眠,进程以 0 退出
  • 停机卡住时第二次信号当场以 1 退出;一直走不完时到时限以 1 退出
  • 同库第二个实例报单实例、以 1 退出,没有开始监听,第一个实例照常回健康检查 200,它的在线电脑没有被踩成休眠
  • 第一个实例 SIGINT 退出后,同库能再起一个;持锁连接被掐断时以 1 退出
  • 健康检查:不登录也回 200;库断了回 503,库恢复后回 200;停机中回 503

先把 src 换回 main 的版本,上面 8 条全红;修复后 8 条全绿。另外做过一次变异:把拿锁挪到 startServer 之后,「第二个实例」那条红在 expected 'sleeping' to be 'online'。

pnpm format:check && pnpm typecheck && pnpm lint      # 通过,lint 0 error
pnpm --filter @baize/control-plane test               # Test Files 119 passed | 1 skipped,Tests 1538 passed | 1 skipped
pnpm --filter @baize/e2e test                         # Test Files 26 passed,Tests 53 passed

没动 web 和 shared,没跑 web 测试。

Closes #24
Closes #25

🤖 Generated with Claude Code

https://claude.ai/code/session_01Be3SZps2JjqvyrJ1vbLmni

@joesmart
joesmart merged commit f41ded7 into main Oct 23, 2026
1 check passed
@joesmart
joesmart deleted the joesmart/ops-shutdown-health branch October 23, 2026 13:50
joesmart added a commit that referenced this pull request Oct 23, 2026
#85 把单实例锁放在启动最前面,缺 TOOL_SECRET_KEY 时会先撞上连库失败,报错不再点名缺的变量。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Be3SZps2JjqvyrJ1vbLmni
joesmart added a commit that referenced this pull request Oct 23, 2026
#85 把单实例锁放在启动最前面,缺 TOOL_SECRET_KEY 时会先撞上连库失败,报错不再点名缺的变量。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Be3SZps2JjqvyrJ1vbLmni
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