Skip to content

Commit bf4fee1

Browse files
committed
feat: support disconnect of prev connection with stable id
1 parent b4ccc48 commit bf4fee1

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

packages/runtime-node/src/ws-node-host.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class WsHost extends BaseHost {
1616

1717
export class WsServerHost extends BaseHost implements IDisposable {
1818
private socketToEnvId = new Map<string, { socket: io.Socket; clientID: string }>();
19+
private clientIdToSocket = new Map<string, io.Socket>();
1920
private disposables = new SafeDisposable(WsServerHost.name);
2021
dispose = this.disposables.dispose;
2122
isDisposed = this.disposables.isDisposed;
@@ -42,7 +43,17 @@ export class WsServerHost extends BaseHost implements IDisposable {
4243
}
4344

4445
private onConnection = (socket: io.Socket): void => {
45-
const nameSpace = (original: string) => `${socket.id}/${original}`;
46+
const clientId = socket.handshake.auth?.clientId || socket.id;
47+
48+
// disconnect previous connection
49+
const existingSocket = this.clientIdToSocket.get(clientId);
50+
if (existingSocket && existingSocket.connected) {
51+
existingSocket.disconnect(true);
52+
}
53+
54+
this.clientIdToSocket.set(clientId, socket);
55+
56+
const nameSpace = (original: string) => `${clientId}/${original}`;
4657
const onMessage = (message: Message): void => {
4758
// this mapping should not be here because of forwarding of messages
4859
// maybe change message forwarding to have 'forward destination' and correct 'from'
@@ -74,6 +85,9 @@ export class WsServerHost extends BaseHost implements IDisposable {
7485
});
7586
}
7687
}
88+
if (this.clientIdToSocket.get(clientId) === socket) {
89+
this.clientIdToSocket.delete(clientId);
90+
}
7791
});
7892
};
7993
}

packages/runtime-node/test/node-com.unit.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,28 @@ describe('Socket communication', () => {
298298
expect(message.from).to.equal('server-host');
299299
});
300300
});
301+
302+
it('Should disconnect previous connection when same clientId reconnects', async () => {
303+
const stableClientId = 'stable-client-id';
304+
const disconnectSpy = sinon.spy();
305+
306+
const firstClient = disposeAfterTest(
307+
new WsClientHost(serverTopology['server-host']!, { auth: { clientId: stableClientId } }),
308+
);
309+
await firstClient.connected;
310+
firstClient.subscribers.on('disconnect', disconnectSpy);
311+
312+
expect(firstClient.isConnected(), 'first connected').to.eql(true);
313+
314+
const secondClient = disposeAfterTest(
315+
new WsClientHost(serverTopology['server-host']!, { auth: { clientId: stableClientId } }),
316+
);
317+
await secondClient.connected;
318+
319+
await waitFor(() => expect(firstClient.isConnected(), 'first disconnected').to.eql(false), { timeout: 2_000 });
320+
expect(disconnectSpy.callCount, 'first disconnected count').to.eq(1);
321+
expect(secondClient.isConnected(), 'second connected').to.eql(true);
322+
});
301323
});
302324

303325
describe('IPC communication', () => {

0 commit comments

Comments
 (0)