feat(server): wire PgEventBus and event-driven settings cache into process assembly

main.ts starts the PG-backed SSE bus (api/worker processes now see each other's events)
and stops it on shutdown; bootstrap passes ctx.events to the settings reader so
settings.changed invalidates every process's cache.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-27 19:59:54 +08:00
1 parent ff230e5da7
commit 1cd523d3e6
2 files changed
+16 -3

No files matched your search

+15 -2
View File
@@ -5,7 +5,7 @@ import denoJson from "../deno.json" with { type: "json" };
import { loadConfig } from "./config.ts";
import { bootstrap } from "./context.ts";
import { createApp } from "./http/app.ts";
import { EventBus } from "./http/sse.ts";
import { PgEventBus } from "./http/sse-pg.ts";
import { createLogger } from "./logger.ts";
import { SERVER_MODULES } from "./modules/index.ts";
import { runPreflight } from "./preflight.ts";
@@ -73,7 +73,19 @@ if (role === "migrate" || role === "preflight") {
Deno.exit(code);
}
const bus = new EventBus();
// SSE 总线:sse_event 表 + LISTEN/NOTIFY,api 与 worker 分进程时事件互相可见
let bus: PgEventBus;
try {
bus = await PgEventBus.start({
db,
connectionString: config.DATABASE_URL,
logger: logger.child({ component: "sse-bus" }),
});
} catch (err) {
logger.error({ err }, "SSE 总线启动失败");
await db.destroy();
Deno.exit(1);
}
const stops: Array<() => Promise<void>> = [];
// 装配 ServerContext:模块注册任务/能力,连接任务引擎(api 角色也要:入队、信号、取消)
@@ -138,6 +150,7 @@ async function shutdown(signal: Deno.Signal) {
const force = setTimeout(() => Deno.exit(1), 10_000);
await Promise.allSettled(stops.map((s) => s()));
await engine.stop().catch((err) => logger.error({ err }, "任务引擎关闭失败"));
await bus.stop().catch(() => {});
await db.destroy();
clearTimeout(force);
Deno.exit(0);