diff --git a/.changeset/fast-goats-notice.md b/.changeset/fast-goats-notice.md new file mode 100644 index 0000000000..65f91a2de0 --- /dev/null +++ b/.changeset/fast-goats-notice.md @@ -0,0 +1,5 @@ +--- +"livekit-client": patch +--- + +Don't treat PC config error as SignalReconnectError diff --git a/src/api/SignalClient.ts b/src/api/SignalClient.ts index 23fd5ddebb..5f900de132 100644 --- a/src/api/SignalClient.ts +++ b/src/api/SignalClient.ts @@ -216,7 +216,7 @@ export class SignalClient { token: string, sid?: string, reason?: ReconnectReason, - ): Promise { + ): Promise { if (!this.options) { this.log.warn( 'attempted to reconnect without signal options being set, ignoring', @@ -242,7 +242,7 @@ export class SignalClient { token: string, opts: ConnectOpts, abortSignal?: AbortSignal, - ): Promise { + ): Promise { this.connectOptions = opts; url = toWebsocketUrl(url); // strip trailing slash @@ -252,7 +252,7 @@ export class SignalClient { const clientInfo = getClientInfo(); const params = createConnectionParams(token, clientInfo, opts); - return new Promise(async (resolve, reject) => { + return new Promise(async (resolve, reject) => { const unlock = await this.connectionLock.lock(); try { const abortHandler = async () => { @@ -356,9 +356,13 @@ export class SignalClient { abortSignal?.removeEventListener('abort', abortHandler); this.startPingInterval(); if (resp.message?.case === 'reconnect') { - resolve(resp.message?.value); + resolve(resp.message.value); } else { - resolve(); + this.log.debug( + 'declaring signal reconnected without reconnect response received', + this.logContext, + ); + resolve(undefined); shouldProcessMessage = true; } } else if (this.isEstablishingConnection && resp.message.case === 'leave') { diff --git a/src/room/RTCEngine.ts b/src/room/RTCEngine.ts index fa71915314..535e57a774 100644 --- a/src/room/RTCEngine.ts +++ b/src/room/RTCEngine.ts @@ -76,6 +76,7 @@ const lossyDataChannel = '_lossy'; const reliableDataChannel = '_reliable'; const minReconnectWait = 2 * 1000; const leaveReconnect = 'leave-reconnect'; +const maxReconnectResponseWait = 2 * 1000; enum PCState { New, @@ -1005,14 +1006,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit this.log.info(`resuming signal connection, attempt ${this.reconnectAttempts}`, this.logContext); this.emit(EngineEvent.Resuming); - + let res: ReconnectResponse | undefined; try { this.setupSignalClientCallbacks(); - const res = await this.client.reconnect(this.url, this.token, this.participantSid, reason); - if (res) { - const rtcConfig = this.makeRTCConfiguration(res); - this.pcManager.updateConfiguration(rtcConfig); - } + res = await this.client.reconnect(this.url, this.token, this.participantSid, reason); } catch (error) { let message = ''; if (error instanceof Error) { @@ -1029,6 +1026,23 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit } this.emit(EngineEvent.SignalResumed); + if (!res) { + const startTime = Date.now(); + while (Date.now() < startTime + maxReconnectResponseWait) { + if (res) { + break; + } + await sleep(50); + } + } + + if (res) { + const rtcConfig = this.makeRTCConfiguration(res); + this.pcManager.updateConfiguration(rtcConfig); + } else { + this.log.warn('Did not receive reconnect response', this.logContext); + } + if (this.shouldFailNext) { this.shouldFailNext = false; throw new Error('simulated failure'); diff --git a/src/room/track/LocalVideoTrack.ts b/src/room/track/LocalVideoTrack.ts index 1ab3585c05..e8a5b3aeab 100644 --- a/src/room/track/LocalVideoTrack.ts +++ b/src/room/track/LocalVideoTrack.ts @@ -424,7 +424,11 @@ async function setPublishingLayersForSender( } if (encodings.length !== senderEncodings.length) { - log.warn('cannot set publishing layers, encodings mismatch'); + log.warn('cannot set publishing layers, encodings mismatch', { + ...logContext, + encodings, + senderEncodings, + }); return; }