feat: 网关 SSE 推送中心——按会话过滤扇出、订阅授权、Last-Event-ID 短窗回放、心跳

This commit is contained in:
lovefyf
2026-08-13 11:53:06 +08:00
parent 41d58a9bb9
commit d308104c0b
8 changed files with 456 additions and 3 deletions
+29 -1
View File
@@ -1,7 +1,35 @@
import { serve } from '@hono/node-server';
import { buildApp } from './app';
import { config } from '../shared/config';
import { closeNats, getNats } from '../shared/bus/nats';
import { SseHub } from '../modules/sse/hub';
serve({ fetch: buildApp().fetch, port: config.port }, (info) => {
const hub = new SseHub();
const app = buildApp(hub);
const server = serve({ fetch: app.fetch, port: config.port }, (info) => {
console.log(`${config.serviceName} listening on :${info.port}`);
});
// NATS 不可达不该拖垮 HTTP 面:代理/上传/健康检查照常,只是没有推送(/health 会照实报 fail)
const nc = await getNats().catch(() => null);
if (nc) hub.attachNats(nc);
else console.warn(`NATS ${config.natsUrl} 不可达——SSE 推送停摆,HTTP 面照常服务`);
/**
* D12:网关此前没有信号处理(N1 靠默认 exit 143)。现在挂着长连 SSE,那些响应永远不结束,
* server.close() 会一直等它们——必须先把连接收掉。3s 兜底强退:任何一环卡住也不赖着不走。
*/
let closing = false;
async function shutdown(signal: string): Promise<void> {
if (closing) return;
closing = true;
console.log(`${signal} 收到——关闭 SSE 连接后退出`);
setTimeout(() => process.exit(0), 3000).unref();
hub.shutdown();
server.close();
if (nc) await closeNats();
process.exit(0);
}
process.on('SIGINT', () => void shutdown('SIGINT'));
process.on('SIGTERM', () => void shutdown('SIGTERM'));