fix(system): retired heartbeat rows no longer alarm on status page

- GET /system/health splits processes into current instances (hosts with
  a beat in the last 10 min, newest per host+kind, not stopped) and
  retiredProcesses[]; 45s stale and level only consider current ones
- heartbeat writer marks stopped_at on graceful exit (migration 0043),
  upsert clears it; pure api role now stops its writer on SIGTERM
- scheduled job system.heartbeat_cleanup (maintain, 1h) deletes rows
  without a beat for 24h and samples older than 7 days
- status page: per-role alarms ("io worker 45 秒没有心跳"), collapsible
  retired instances; glossary/runbook updated
- bump all members to 0.2.2, CHANGELOG [0.2.2]

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-28 23:31:21 +08:00
1 parent fa261eb6cd
commit b4c9b1ead2
32 files changed
+747 -91

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@umt/db",
"version": "0.2.0",
"version": "0.2.2",
"exports": { ".": "./src/index.ts" },
"tasks": {
"test": "deno run -A npm:vitest run",
@@ -0,0 +1,16 @@
import type { Kysely } from "kysely";
import { execDdl } from "../src/migration-helpers.ts";
// 心跳残留修复:进程正常退出(SIGTERM / SIGINT)时把自己的行标 stopped_at,读取方立即把它当已下线实例,
// 不再等 45s 判 stale。重启后同一 instance_id 的 upsert 把 stopped_at 清回 null。
// 超过 24 小时没心跳的行由定时任务 system.heartbeat_cleanup 删除。
// biome-ignore lint/suspicious/noExplicitAny: 迁移不依赖应用表类型
export async function up(db: Kysely<any>): Promise<void> {
await execDdl(db, `alter table process_heartbeat add column stopped_at timestamptz;`);
}
// biome-ignore lint/suspicious/noExplicitAny: 同上
export async function down(db: Kysely<any>): Promise<void> {
await execDdl(db, `alter table process_heartbeat drop column if exists stopped_at;`);
}
+1 -1
View File
@@ -1,5 +1,5 @@
// 统一从本包取 Kysely 与 sql,避免各包各装一份 kysely
export { type Kysely, sql, type Transaction } from "kysely";
export { type Kysely, type Selectable, sql, type Transaction } from "kysely";
export {
type CachedOptions,
cachedCall,
+1
View File
@@ -1152,6 +1152,7 @@ export interface ProcessHeartbeatTable {
concurrency: Generated<Json>;
running_runs: number | null;
extra: Generated<Json>;
stopped_at: Timestamptz | null;
}
export interface ProcessHeartbeatSampleTable {