[bugfix] Safely subscribe to on stateChanged events to prevent related events from failing if listeners throw an error (#5165)
* Safely subscribe to on stateChanged events to prevent related events from failing if listeners throw an error * Ensure anonymous function can be subscribed and unsubscribed * Resolve linter issues * Update unsubscription calls * Resolve linter issues * Update CallErrorTarget * Change files
This commit is contained in:
Родитель
bbc495137c
Коммит
39e34af998
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type": "patch",
|
||||
"area": "fix",
|
||||
"workstream": "CallSubscriber",
|
||||
"comment": "Safely subscribe to on stateChanged events to prevent related events from failing if listeners throw an error",
|
||||
"packageName": "@azure/communication-react",
|
||||
"email": "edwardlee@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type": "patch",
|
||||
"area": "fix",
|
||||
"workstream": "CallSubscriber",
|
||||
"comment": "Safely subscribe to on stateChanged events to prevent related events from failing if listeners throw an error",
|
||||
"packageName": "@azure/communication-react",
|
||||
"email": "edwardlee@microsoft.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -123,12 +123,25 @@ export class CallSubscriber {
|
|||
this.subscribe();
|
||||
}
|
||||
|
||||
private _safeSubscribeInitCaptionSubscriber = (): void => {
|
||||
this._safeSubscribe(this.initCaptionSubscriber);
|
||||
};
|
||||
|
||||
private _safeSubscribeInitTeamsMeetingConference = (): void => {
|
||||
this._safeSubscribe(this.initTeamsMeetingConference);
|
||||
};
|
||||
|
||||
/* @conditional-compile-remove(local-recording-notification) */
|
||||
private _safeSubscribeInitLocalRecordingNotificationSubscriber = (): void => {
|
||||
this._safeSubscribe(this.initLocalRecordingNotificationSubscriber);
|
||||
};
|
||||
|
||||
private subscribe = (): void => {
|
||||
this._call.on('stateChanged', this.stateChanged);
|
||||
this._call.on('stateChanged', this.initCaptionSubscriber);
|
||||
this._call.on('stateChanged', this.initTeamsMeetingConference);
|
||||
this._call.on('stateChanged', this._safeSubscribeInitCaptionSubscriber);
|
||||
this._call.on('stateChanged', this._safeSubscribeInitTeamsMeetingConference);
|
||||
/* @conditional-compile-remove(local-recording-notification) */
|
||||
this._call.on('stateChanged', this.initLocalRecordingNotificationSubscriber);
|
||||
this._call.on('stateChanged', this._safeSubscribeInitLocalRecordingNotificationSubscriber);
|
||||
this._call.on('idChanged', this.idChanged);
|
||||
this._call.on('isScreenSharingOnChanged', this.isScreenSharingOnChanged);
|
||||
this._call.on('remoteParticipantsUpdated', this.remoteParticipantsUpdated);
|
||||
|
@ -166,11 +179,10 @@ export class CallSubscriber {
|
|||
|
||||
public unsubscribe = (): void => {
|
||||
this._call.off('stateChanged', this.stateChanged);
|
||||
this._call.off('stateChanged', this.initCaptionSubscriber);
|
||||
this._call.off('stateChanged', this._safeSubscribeInitCaptionSubscriber);
|
||||
this._call.off('stateChanged', this._safeSubscribeInitTeamsMeetingConference);
|
||||
/* @conditional-compile-remove(local-recording-notification) */
|
||||
this._call.off('stateChanged', this.initLocalRecordingNotificationSubscriber);
|
||||
|
||||
this._call.off('stateChanged', this.initTeamsMeetingConference);
|
||||
this._call.off('stateChanged', this._safeSubscribeInitLocalRecordingNotificationSubscriber);
|
||||
this._call.off('idChanged', this.idChanged);
|
||||
this._call.off('isScreenSharingOnChanged', this.isScreenSharingOnChanged);
|
||||
this._call.off('remoteParticipantsUpdated', this.remoteParticipantsUpdated);
|
||||
|
@ -218,6 +230,18 @@ export class CallSubscriber {
|
|||
this._breakoutRoomsSubscriber.unsubscribe();
|
||||
};
|
||||
|
||||
// This is a helper function to safely call subscriber functions. This is needed in order to prevent events
|
||||
// with the same event type from failing to fire due to a subscriber throwing an error upon subscription.
|
||||
// Wrap your listeners with this helper function if your listener can fail due to initialization or fail
|
||||
// during a function call. This will prevent other events using the same event type from failing to fire.
|
||||
private _safeSubscribe(subscriber: () => void): void {
|
||||
try {
|
||||
subscriber();
|
||||
} catch (e) {
|
||||
this._context.teeErrorToState(e as Error, 'Call.on');
|
||||
}
|
||||
}
|
||||
|
||||
private addParticipantListener(participant: RemoteParticipant): void {
|
||||
const participantKey = toFlatCommunicationIdentifier(participant.identifier);
|
||||
this._participantSubscribers.get(participantKey)?.unsubscribe();
|
||||
|
@ -248,7 +272,7 @@ export class CallSubscriber {
|
|||
this._context,
|
||||
this._call.feature(Features.Captions)
|
||||
);
|
||||
this._call.off('stateChanged', this.initCaptionSubscriber);
|
||||
this._call.off('stateChanged', this._safeSubscribeInitCaptionSubscriber);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -260,7 +284,7 @@ export class CallSubscriber {
|
|||
.then((teamsMeetingConferenceDetails) => {
|
||||
this._context.setTeamsMeetingConference(this._callIdRef.callId, teamsMeetingConferenceDetails);
|
||||
});
|
||||
this._call.off('stateChanged', this.initTeamsMeetingConference);
|
||||
this._call.off('stateChanged', this._safeSubscribeInitTeamsMeetingConference);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -274,7 +298,7 @@ export class CallSubscriber {
|
|||
this._context,
|
||||
this._call.feature(Features.LocalRecording)
|
||||
);
|
||||
this._call.off('stateChanged', this.initLocalRecordingNotificationSubscriber);
|
||||
this._call.off('stateChanged', this._safeSubscribeInitLocalRecordingNotificationSubscriber);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче