feat(gateway): add optional bonjour/mdns discovery
This commit is contained in:
+50
-1
@@ -9,6 +9,7 @@ import { LaneQueue } from './lane-queue.js';
|
||||
import { MetricsCollector } from './metrics.js';
|
||||
import { authenticateRequest } from './auth.js';
|
||||
import type { AuthConfig } from './auth.js';
|
||||
import { startGatewayDiscovery, type GatewayDiscoveryHandle } from './discovery.js';
|
||||
import {
|
||||
parseMessage,
|
||||
makeError,
|
||||
@@ -86,6 +87,12 @@ export interface GatewayServerConfig {
|
||||
commandRegistry?: CommandRegistry;
|
||||
intentRegistry?: ComponentRegistry;
|
||||
routingPolicy?: RoutingPolicy;
|
||||
discovery?: {
|
||||
enabled: boolean;
|
||||
serviceName: string;
|
||||
serviceType: string;
|
||||
txtRecord?: Record<string, string>;
|
||||
};
|
||||
}
|
||||
|
||||
export class GatewayServer {
|
||||
@@ -103,6 +110,7 @@ export class GatewayServer {
|
||||
private sessionBridge: SessionBridge;
|
||||
private laneQueue: LaneQueue;
|
||||
private metrics: MetricsCollector;
|
||||
private discoveryHandle: GatewayDiscoveryHandle | null = null;
|
||||
private connectionMap: Map<WebSocket, string> = new Map();
|
||||
private connectionRateMap: Map<string, {
|
||||
tokens: number;
|
||||
@@ -272,12 +280,24 @@ export class GatewayServer {
|
||||
|
||||
this.httpServer.listen(port, host, () => {
|
||||
console.log(`Gateway server listening on ${host}:${port}`);
|
||||
resolve();
|
||||
void this.startDiscovery(host, port).finally(() => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async stop(): Promise<void> {
|
||||
if (this.discoveryHandle) {
|
||||
try {
|
||||
await this.discoveryHandle.stop();
|
||||
} catch (err) {
|
||||
console.error('Failed to stop mDNS discovery:', err instanceof Error ? err.message : err);
|
||||
} finally {
|
||||
this.discoveryHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Close all WebSocket connections first
|
||||
for (const [ws, connectionId] of this.connectionMap) {
|
||||
this.sessionBridge.disconnect(connectionId);
|
||||
@@ -543,6 +563,35 @@ export class GatewayServer {
|
||||
this.config.gmailHandler = handler;
|
||||
}
|
||||
|
||||
private async startDiscovery(host: string, port: number): Promise<void> {
|
||||
const discovery = this.config.discovery;
|
||||
if (!discovery?.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (host === '127.0.0.1' || host === '::1') {
|
||||
console.warn('mDNS discovery is enabled, but server.localhost=true restricts gateway to loopback; skipping advertisement');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const txtRecord: Record<string, string> = {
|
||||
instance: `pid-${process.pid}`,
|
||||
version: this.config.version ?? '0.1.0',
|
||||
...(discovery.txtRecord ?? {}),
|
||||
};
|
||||
this.discoveryHandle = await startGatewayDiscovery({
|
||||
serviceName: discovery.serviceName,
|
||||
serviceType: discovery.serviceType,
|
||||
port,
|
||||
txtRecord,
|
||||
});
|
||||
console.log(`mDNS discovery enabled: ${discovery.serviceName}.${discovery.serviceType}.local:${port}`);
|
||||
} catch (err) {
|
||||
console.warn(`mDNS discovery failed to start: ${err instanceof Error ? err.message : String(err)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** Read the full request body as a string. */
|
||||
private readRequestBody(req: IncomingMessage): Promise<string> {
|
||||
const maxBytes = this.config.maxRequestBodyBytes ?? GatewayServer.DEFAULT_MAX_REQUEST_BODY_BYTES;
|
||||
|
||||
Reference in New Issue
Block a user