Skip to content

Commit

Permalink
Grace period for websocket to close gracefully (#514)
Browse files Browse the repository at this point in the history
* grace period for ws to close gracefully

* changeset
  • Loading branch information
lukasIO committed Nov 29, 2022
1 parent dade768 commit 6a748fc
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/mean-flies-happen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'livekit-client': patch
---

grace period for WS to close gracefully
22 changes: 21 additions & 1 deletion src/api/SignalClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,13 +301,33 @@ export class SignalClient {
});
}

close() {
async close() {
this.isConnected = false;
if (this.ws) {
this.ws.onclose = null;
this.ws.onmessage = null;
this.ws.onopen = null;

const emptyBufferPromise = new Promise(async (resolve) => {
while (this.ws && this.ws.bufferedAmount > 0) {
await sleep(50);
}
resolve(true);
});
// 250ms grace period for buffer to be cleared
await Promise.race([emptyBufferPromise, sleep(250)]);

let closeResolver: (args: any) => void;
const closePromise = new Promise((resolve) => {
closeResolver = resolve;
});

// calling `ws.close()` only starts the closing handshake (CLOSING state), prefer to wait until state is actually CLOSED
this.ws.onclose = () => closeResolver(true);

this.ws.close();
// 250ms grace period for ws to close gracefully
await Promise.race([closePromise, sleep(250)]);
}
this.ws = undefined;
this.clearPingInterval();
Expand Down
2 changes: 1 addition & 1 deletion src/connectionHelper/checks/turn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class TURNCheck extends Checker {
} else if (hasTURN && !hasTLS) {
this.appendWarning('TURN is configured server side, but TURN/TLS is unavailable.');
}
signalClient.close();
await signalClient.close();
if (this.connectOptions?.rtcConfig?.iceServers || hasTURN) {
await this.room!.connect(this.url, this.token, {
rtcConfig: {
Expand Down
2 changes: 1 addition & 1 deletion src/connectionHelper/checks/websocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ export class WebSocketCheck extends Checker {
maxRetries: 0,
});
this.appendMessage(`Connected to server, version ${joinRes.serverVersion}.`);
signalClient.close();
await signalClient.close();
}
}
8 changes: 4 additions & 4 deletions src/room/RTCEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
}
}

close() {
async close() {
this._isClosed = true;
this.removeAllListeners();
this.deregisterOnLineListener();
Expand All @@ -202,7 +202,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
this.subscriber.close();
this.subscriber = undefined;
}
this.client.close();
await this.client.close();
}

addTrack(req: AddTrackRequest): Promise<TrackInfo> {
Expand Down Expand Up @@ -784,9 +784,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
}

if (this.client.isConnected) {
this.client.sendLeave();
await this.client.sendLeave();
}
this.client.close();
await this.client.close();
this.primaryPC = undefined;
this.publisher?.close();
this.publisher = undefined;
Expand Down
10 changes: 5 additions & 5 deletions src/room/Room.ts
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
}
// close engine (also closes client)
if (this.engine) {
this.engine.close();
await this.engine.close();
}
this.handleDisconnect(stopTracks, DisconnectReason.CLIENT_INITIATED);
/* @ts-ignore */
Expand Down Expand Up @@ -440,12 +440,12 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
/**
* @internal for testing
*/
simulateScenario(scenario: string) {
async simulateScenario(scenario: string) {
let postAction = () => {};
let req: SimulateScenario | undefined;
switch (scenario) {
case 'signal-reconnect':
this.engine.client.close();
await this.engine.client.close();
if (this.engine.client.onClose) {
this.engine.client.onClose('simulate disconnect');
}
Expand Down Expand Up @@ -508,8 +508,8 @@ class Room extends (EventEmitter as new () => TypedEmitter<RoomEventCallbacks>)
}
}

private onBeforeUnload = () => {
this.disconnect();
private onBeforeUnload = async () => {
await this.disconnect();
};

/**
Expand Down

0 comments on commit 6a748fc

Please sign in to comment.