feat(core): Add heartbeat grace/timeout options, client retry/wait-for-ready, server readiness and socket cleanup, transport socket options, helper utilities, and tests

This commit is contained in:
2025-08-25 13:37:31 +00:00
parent e3c1d35895
commit dd25ffd3e4
9 changed files with 780 additions and 30 deletions

View File

@@ -7,7 +7,7 @@ import { IpcServer } from './classes.ipcserver.js';
import { IpcClient } from './classes.ipcclient.js';
import { IpcChannel } from './classes.ipcchannel.js';
import type { IIpcServerOptions } from './classes.ipcserver.js';
import type { IIpcClientOptions } from './classes.ipcclient.js';
import type { IIpcClientOptions, IConnectRetryConfig } from './classes.ipcclient.js';
import type { IIpcChannelOptions } from './classes.ipcchannel.js';
/**
@@ -17,6 +17,89 @@ export class SmartIpc {
/**
* Create an IPC server
*/
/**
* Wait for a server to become ready at the given socket path
*/
public static async waitForServer(options: {
socketPath: string;
timeoutMs?: number;
}): Promise<void> {
const timeout = options.timeoutMs || 10000;
const startTime = Date.now();
while (Date.now() - startTime < timeout) {
try {
// Try to connect as a temporary client
const testClient = new IpcClient({
id: `test-probe-${Date.now()}`,
socketPath: options.socketPath,
autoReconnect: false,
heartbeat: false
});
await testClient.connect();
await testClient.disconnect();
return; // Server is ready
} catch (error) {
// Server not ready yet, wait and retry
await new Promise(resolve => setTimeout(resolve, 100));
}
}
throw new Error(`Server not ready at ${options.socketPath} after ${timeout}ms`);
}
/**
* Helper to spawn a server process and connect a client
*/
public static async spawnAndConnect(options: {
serverScript: string;
socketPath: string;
clientId?: string;
spawnOptions?: any;
connectRetry?: IConnectRetryConfig;
timeoutMs?: number;
}): Promise<{
client: IpcClient;
serverProcess: any;
}> {
const { spawn } = await import('child_process');
// Spawn the server process
const serverProcess = spawn('node', [options.serverScript], {
detached: true,
stdio: 'pipe',
...options.spawnOptions
});
// Handle server process errors
serverProcess.on('error', (error: Error) => {
console.error('Server process error:', error);
});
// Wait for server to be ready
await SmartIpc.waitForServer({
socketPath: options.socketPath,
timeoutMs: options.timeoutMs || 10000
});
// Create and connect client
const client = new IpcClient({
id: options.clientId || 'test-client',
socketPath: options.socketPath,
connectRetry: options.connectRetry || {
enabled: true,
maxAttempts: 10,
initialDelay: 100,
maxDelay: 1000
}
});
await client.connect({ waitForReady: true });
return { client, serverProcess };
}
public static createServer(options: IIpcServerOptions): IpcServer {
return new IpcServer(options);
}