import { connect } from 'nats'; import type { NatsConnection } from 'nats'; import { config } from '../config'; let nc: NatsConnection | null = null; /** * 在途去重:nc 只在 connect() **resolve 之后**才被赋值,所以并发的首批调用者读到的 * 都还是 null,于是各自拨一条连接;最后一个赋值进 nc,前面那些谁也够不着——drain 不掉、 * 也不计入 closeNats,就那么挂在服务端的连接表上直到进程死。记住这次在途的 promise, * 让并发调用者共享同一次拨号;成功与失败都清空,失败后下一次调用可以重新拨。 */ let connecting: Promise | null = null; export async function getNats(): Promise { if (nc && !nc.isClosed()) return nc; if (connecting) return await connecting; const dial = connect({ servers: config.natsUrl, name: config.serviceName, timeout: 5000 }) .then((c) => { nc = c; connecting = null; return c; }) .catch((err: unknown) => { connecting = null; throw err; }); connecting = dial; return await dial; } export async function checkNats(): Promise<'ok' | 'fail'> { try { const c = await getNats(); await c.flush(); return 'ok'; } catch { return 'fail'; } } export async function closeNats(): Promise { if (nc) { await nc.drain().catch(() => {}); nc = null; } }