From 723c076ae235492262d1dbd84c6441d8b512843e Mon Sep 17 00:00:00 2001 From: lukasIO Date: Thu, 21 Nov 2024 12:02:59 +0100 Subject: [PATCH 1/5] Forward disconnect reason on leave requests --- src/api/SignalClient.ts | 2 ++ src/room/Room.ts | 18 ++++++++++++++++-- src/room/errors.ts | 12 ++++++++++-- src/room/participant/LocalParticipant.ts | 17 ++++++++++++----- 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/api/SignalClient.ts b/src/api/SignalClient.ts index 0bcc8a4b11..8992f3519e 100644 --- a/src/api/SignalClient.ts +++ b/src/api/SignalClient.ts @@ -394,6 +394,8 @@ export class SignalClient { new ConnectionError( 'Received leave request while trying to (re)connect', ConnectionErrorReason.LeaveRequest, + undefined, + resp.message.value.reason, ), ); } else if (!opts.reconnect) { diff --git a/src/room/Room.ts b/src/room/Room.ts index 6baa880f9d..6b73198ad8 100644 --- a/src/room/Room.ts +++ b/src/room/Room.ts @@ -562,11 +562,25 @@ class Room extends (EventEmitter as new () => TypedEmitter) this.recreateEngine(); await connectFn(resolve, reject, nextUrl); } else { - this.handleDisconnect(this.options.stopLocalTrackOnUnpublish); + let disconnectReason = DisconnectReason.UNKNOWN_REASON; + if (e.reason === ConnectionErrorReason.LeaveRequest && e.context) { + disconnectReason = e.context as DisconnectReason; + } else if (e.reason === ConnectionErrorReason.ServerUnreachable) { + disconnectReason = DisconnectReason.JOIN_FAILURE; + } + this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, disconnectReason); reject(e); } } else { - this.handleDisconnect(this.options.stopLocalTrackOnUnpublish); + let disconnectReason = DisconnectReason.UNKNOWN_REASON; + if (e instanceof ConnectionError) { + if (e.reason === ConnectionErrorReason.Cancelled) { + disconnectReason = DisconnectReason.CLIENT_INITIATED; + } else if (e.reason === ConnectionErrorReason.NotAllowed) { + disconnectReason = DisconnectReason.USER_REJECTED; + } + } + this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, disconnectReason); reject(e); } } diff --git a/src/room/errors.ts b/src/room/errors.ts index 80f39c7f90..14bb30d92e 100644 --- a/src/room/errors.ts +++ b/src/room/errors.ts @@ -1,4 +1,4 @@ -import { RequestResponse_Reason } from '@livekit/protocol'; +import { DisconnectReason, RequestResponse_Reason } from '@livekit/protocol'; export class LivekitError extends Error { code: number; @@ -20,12 +20,20 @@ export const enum ConnectionErrorReason { export class ConnectionError extends LivekitError { status?: number; + context?: unknown | DisconnectReason; + reason: ConnectionErrorReason; - constructor(message: string, reason: ConnectionErrorReason, status?: number) { + constructor( + message: string, + reason: ConnectionErrorReason, + status?: number, + context?: unknown | DisconnectReason, + ) { super(1, message); this.status = status; this.reason = reason; + this.context = context; } } diff --git a/src/room/participant/LocalParticipant.ts b/src/room/participant/LocalParticipant.ts index a6916197fb..93049f5e7f 100644 --- a/src/room/participant/LocalParticipant.ts +++ b/src/room/participant/LocalParticipant.ts @@ -2016,11 +2016,18 @@ export default class LocalParticipant extends Participant { } private async waitForPendingPublicationOfSource(source: Track.Source) { - const publishPromiseEntry = Array.from(this.pendingPublishPromises.entries()).find( - ([pendingTrack]) => pendingTrack.source === source, - ); - if (publishPromiseEntry) { - return publishPromiseEntry[1]; + const waitForPendingTimeout = 10_000; + const startTime = Date.now(); + + while (Date.now() < startTime + waitForPendingTimeout) { + const publishPromiseEntry = Array.from(this.pendingPublishPromises.entries()).find( + ([pendingTrack]) => pendingTrack.source === source, + ); + if (publishPromiseEntry) { + return publishPromiseEntry[1]; + } + sleep(20); } + throw new Error('waiting for pending publication promise timed out'); } } From deae20ca048461fba2f34584982b0531c2b7f3c7 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Thu, 21 Nov 2024 12:09:36 +0100 Subject: [PATCH 2/5] util --- src/room/Room.ts | 18 ++++++------------ src/room/utils.ts | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/room/Room.ts b/src/room/Room.ts index 6b73198ad8..ce9e7235c1 100644 --- a/src/room/Room.ts +++ b/src/room/Room.ts @@ -81,6 +81,7 @@ import { createDummyVideoStreamTrack, extractChatMessage, extractTranscriptionSegments, + getDisconnectReasonFromConnectionError, getEmptyAudioStreamTrack, isBrowserSupported, isCloud, @@ -562,23 +563,16 @@ class Room extends (EventEmitter as new () => TypedEmitter) this.recreateEngine(); await connectFn(resolve, reject, nextUrl); } else { - let disconnectReason = DisconnectReason.UNKNOWN_REASON; - if (e.reason === ConnectionErrorReason.LeaveRequest && e.context) { - disconnectReason = e.context as DisconnectReason; - } else if (e.reason === ConnectionErrorReason.ServerUnreachable) { - disconnectReason = DisconnectReason.JOIN_FAILURE; - } - this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, disconnectReason); + this.handleDisconnect( + this.options.stopLocalTrackOnUnpublish, + getDisconnectReasonFromConnectionError(e), + ); reject(e); } } else { let disconnectReason = DisconnectReason.UNKNOWN_REASON; if (e instanceof ConnectionError) { - if (e.reason === ConnectionErrorReason.Cancelled) { - disconnectReason = DisconnectReason.CLIENT_INITIATED; - } else if (e.reason === ConnectionErrorReason.NotAllowed) { - disconnectReason = DisconnectReason.USER_REJECTED; - } + disconnectReason = getDisconnectReasonFromConnectionError(e); } this.handleDisconnect(this.options.stopLocalTrackOnUnpublish, disconnectReason); reject(e); diff --git a/src/room/utils.ts b/src/room/utils.ts index 7fbb9e3246..3b8c427310 100644 --- a/src/room/utils.ts +++ b/src/room/utils.ts @@ -2,10 +2,12 @@ import { ChatMessage as ChatMessageModel, ClientInfo, ClientInfo_SDK, + DisconnectReason, Transcription as TranscriptionModel, } from '@livekit/protocol'; import { getBrowser } from '../utils/browserParser'; import { protocolVersion, version } from '../version'; +import { type ConnectionError, ConnectionErrorReason } from './errors'; import CriticalTimers from './timers'; import type LocalAudioTrack from './track/LocalAudioTrack'; import type RemoteAudioTrack from './track/RemoteAudioTrack'; @@ -531,3 +533,18 @@ export function extractChatMessage(msg: ChatMessageModel): ChatMessage { message, }; } + +export function getDisconnectReasonFromConnectionError(e: ConnectionError) { + switch (e.reason) { + case ConnectionErrorReason.LeaveRequest: + return e.context as DisconnectReason; + case ConnectionErrorReason.Cancelled: + return DisconnectReason.CLIENT_INITIATED; + case ConnectionErrorReason.NotAllowed: + return DisconnectReason.USER_REJECTED; + case ConnectionErrorReason.ServerUnreachable: + return DisconnectReason.JOIN_FAILURE; + default: + return DisconnectReason.UNKNOWN_REASON; + } +} From c5e05df810bd6ab96d6a89c2dbfdd3781d3179f4 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Thu, 21 Nov 2024 12:13:34 +0100 Subject: [PATCH 3/5] revert pending publish await change --- src/room/participant/LocalParticipant.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/room/participant/LocalParticipant.ts b/src/room/participant/LocalParticipant.ts index 93049f5e7f..a6916197fb 100644 --- a/src/room/participant/LocalParticipant.ts +++ b/src/room/participant/LocalParticipant.ts @@ -2016,18 +2016,11 @@ export default class LocalParticipant extends Participant { } private async waitForPendingPublicationOfSource(source: Track.Source) { - const waitForPendingTimeout = 10_000; - const startTime = Date.now(); - - while (Date.now() < startTime + waitForPendingTimeout) { - const publishPromiseEntry = Array.from(this.pendingPublishPromises.entries()).find( - ([pendingTrack]) => pendingTrack.source === source, - ); - if (publishPromiseEntry) { - return publishPromiseEntry[1]; - } - sleep(20); + const publishPromiseEntry = Array.from(this.pendingPublishPromises.entries()).find( + ([pendingTrack]) => pendingTrack.source === source, + ); + if (publishPromiseEntry) { + return publishPromiseEntry[1]; } - throw new Error('waiting for pending publication promise timed out'); } } From cb6d2e6af4953fb815158a2035a68a39ea6da9df Mon Sep 17 00:00:00 2001 From: lukasIO Date: Thu, 21 Nov 2024 12:14:51 +0100 Subject: [PATCH 4/5] Create wicked-frogs-beg.md --- .changeset/wicked-frogs-beg.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wicked-frogs-beg.md diff --git a/.changeset/wicked-frogs-beg.md b/.changeset/wicked-frogs-beg.md new file mode 100644 index 0000000000..279ec48fce --- /dev/null +++ b/.changeset/wicked-frogs-beg.md @@ -0,0 +1,5 @@ +--- +"livekit-client": patch +--- + +Forward disconnect reason on leave requests From 7bbbda09a5cc7eaa2496607eb435aacfd0d76ae8 Mon Sep 17 00:00:00 2001 From: lukasIO Date: Thu, 21 Nov 2024 13:03:05 +0100 Subject: [PATCH 5/5] Update wicked-frogs-beg.md --- .changeset/wicked-frogs-beg.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/wicked-frogs-beg.md b/.changeset/wicked-frogs-beg.md index 279ec48fce..ebd378c0bc 100644 --- a/.changeset/wicked-frogs-beg.md +++ b/.changeset/wicked-frogs-beg.md @@ -2,4 +2,4 @@ "livekit-client": patch --- -Forward disconnect reason on leave requests +Forward disconnect reason on leave requests and ConnectionErrors