Skip to content

Commit 9bff878

Browse files
emit close on websocket (#44)
1 parent 8e9a316 commit 9bff878

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

.changeset/nasty-mugs-battle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@powersync/service-rsocket-router': patch
3+
---
4+
5+
Fix issue where WebSocket close events would not immediately propagate to router handlers.

packages/rsocket-router/src/router/transport/WebSocketServerTransport.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ export class WebsocketServerTransport implements ServerTransport {
7474
try {
7575
websocket.binaryType = 'nodebuffer';
7676
const duplex = WebSocket.createWebSocketStream(websocket);
77+
websocket.on('close', (e) => {
78+
duplex.emit('close', e);
79+
});
7780
WebsocketDuplexConnection.create(duplex, connectionAcceptor, multiplexerDemultiplexerFactory, websocket);
7881
} catch (ex) {
7982
logger.error(`Could not create duplex connection`, ex);

packages/rsocket-router/tests/src/socket.test.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,9 @@ describe('Sockets', () => {
124124
wsCreator: () => server
125125
});
126126

127+
const onCancelWrapper = (callback: () => void) => callback();
128+
const serverCancelSpy = vi.fn(onCancelWrapper);
129+
127130
// Create a simple server which will spam a lot of data to any connection
128131
const rSocketServer = new RSocketServer({
129132
transport,
@@ -143,7 +146,9 @@ describe('Sockets', () => {
143146
request: () => {},
144147
onExtension: () => {},
145148
cancel: () => {
146-
stop = true;
149+
serverCancelSpy(() => {
150+
stop = true;
151+
});
147152
}
148153
};
149154
}
@@ -154,7 +159,8 @@ describe('Sockets', () => {
154159
rSocketServer.bind();
155160

156161
// Try and connect 100 times, closing the socket as soon as it is available
157-
for (let i = 0; i < 100; i++) {
162+
const testCount = 100;
163+
const promises = new Array(testCount).fill(null).map(async () => {
158164
const testSocket = new WebSocket.WebSocket(WS_ADDRESS);
159165

160166
const connector = new RSocketConnector({
@@ -166,13 +172,18 @@ describe('Sockets', () => {
166172
setup: {
167173
dataMimeType: 'application/bson',
168174
metadataMimeType: 'application/bson',
175+
176+
keepAlive: 20000,
177+
lifetime: 30000,
178+
169179
payload: {
170180
data: null
171181
}
172182
}
173183
});
174184

175185
const connection = await connector.connect();
186+
176187
connection.requestStream({ data: null }, 1, {
177188
onNext() {},
178189
onComplete: () => {},
@@ -182,6 +193,9 @@ describe('Sockets', () => {
182193

183194
// The socket closing here should not throw any unhandled errors
184195
testSocket.close();
185-
}
196+
});
197+
198+
await Promise.all(promises);
199+
await vi.waitFor(() => expect(serverCancelSpy.mock.calls.length).equals(testCount), { timeout: 2000 });
186200
});
187201
});

0 commit comments

Comments
 (0)