From 137ca9cbe75f2ddbe5e14908572b5f93a1ab7e4b Mon Sep 17 00:00:00 2001 From: Bruno Tutrut Date: Fri, 11 Aug 2023 08:55:38 -0300 Subject: [PATCH 1/2] feat: added event when host availability changes --- src/common/types/events.types.ts | 2 ++ src/services/communicator/ index.test.ts | 2 ++ src/services/communicator/index.ts | 20 ++++++++++++++++++-- src/services/realtime/ably/index.ts | 6 ++++-- src/services/realtime/base/index.ts | 6 ++++-- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/common/types/events.types.ts b/src/common/types/events.types.ts index a6aa6149..e1a15263 100644 --- a/src/common/types/events.types.ts +++ b/src/common/types/events.types.ts @@ -43,6 +43,8 @@ export enum RealtimeEvent { REALTIME_JOIN = 'realtime.join', REALTIME_PARTICIPANT_LIST_UPDATE = 'realtime.participant-list-update', REALTIME_HOST_CHANGE = 'realtime.host-change', + REALTIME_HOST_AVAILABLE = 'realtime.host-available', + REALTIME_NO_HOST_AVAILABLE = 'realtime.no-host-available', REALTIME_GRID_MODE_CHANGE = 'realtime.grid-mode-change', REALTIME_WAIT_FOR_HOST = 'realtime.wait-for-host', REALTIME_AUTHENTICATION_FAILED = 'realtime.authentication-failed', diff --git a/src/services/communicator/ index.test.ts b/src/services/communicator/ index.test.ts index 19c8b94f..bb0bcb67 100644 --- a/src/services/communicator/ index.test.ts +++ b/src/services/communicator/ index.test.ts @@ -66,6 +66,7 @@ const AblyRealtimeMock = { participantJoinedObserver: MOCK_OBSERVER_HELPER, participantLeaveObserver: MOCK_OBSERVER_HELPER, hostObserver: MOCK_OBSERVER_HELPER, + hostAvailabilityObserver: MOCK_OBSERVER_HELPER, syncPropertiesObserver: MOCK_OBSERVER_HELPER, kickAllParticipantsObserver: MOCK_OBSERVER_HELPER, authenticationObserver: MOCK_OBSERVER_HELPER, @@ -217,6 +218,7 @@ describe('Communicator', () => { expect(AblyRealtimeMock.participantJoinedObserver.unsubscribe).toBeCalled(); expect(AblyRealtimeMock.participantLeaveObserver.unsubscribe).toBeCalled(); expect(AblyRealtimeMock.hostObserver.unsubscribe).toBeCalled(); + expect(AblyRealtimeMock.hostAvailabilityObserver.unsubscribe).toBeCalled(); expect(AblyRealtimeMock.syncPropertiesObserver.unsubscribe).toBeCalled(); expect(AblyRealtimeMock.kickAllParticipantsObserver.unsubscribe).toBeCalled(); expect(AblyRealtimeMock.authenticationObserver.unsubscribe).toBeCalled(); diff --git a/src/services/communicator/index.ts b/src/services/communicator/index.ts index ac7c4623..2c7b6765 100644 --- a/src/services/communicator/index.ts +++ b/src/services/communicator/index.ts @@ -145,6 +145,7 @@ class Communicator { this.realtime.syncPropertiesObserver.subscribe(this.onSyncPropertiesDidChange); this.realtime.kickAllParticipantsObserver.subscribe(this.onKickAllParticipantsDidChange); this.realtime.authenticationObserver.subscribe(this.onAuthenticationFailed); + this.realtime.hostAvailabilityObserver.subscribe(this.onHostAvailabilityDidChange); this.realtime.start({ initialParticipantData: { @@ -265,7 +266,7 @@ class Communicator { /** * @function publishMeetingControlEvent - * @param event: MeetingControlsEvent + * @param {MeetingControlsEvent} event * @description publish event to meeting controls * @returns {void} */ @@ -569,6 +570,21 @@ class Communicator { } }; + /** + * @function onHostAvailabilityDidChange + * @description handler for host availability inside room + * @param {boolean} hasHost + * @return {void} + */ + + private onHostAvailabilityDidChange = (hasHost: boolean): void => { + if (hasHost) { + this.publish(RealtimeEvent.REALTIME_HOST_AVAILABLE); + return; + } + this.publish(RealtimeEvent.REALTIME_NO_HOST_AVAILABLE); + }; + /** * @function onGridModeDidChange * @description handler for grid mode change event @@ -698,7 +714,7 @@ class Communicator { }; /** - * @function onCOnnectionStatusChange + * @function onConnectionStatusChange * @description handler for connection status change event * @param {MeetingConnectionStatus} newStatus - new connection status * @returns {void} diff --git a/src/services/realtime/ably/index.ts b/src/services/realtime/ably/index.ts index 0a6d01cf..8047f110 100644 --- a/src/services/realtime/ably/index.ts +++ b/src/services/realtime/ably/index.ts @@ -163,7 +163,7 @@ export default class AblyRealtimeService extends RealtimeService implements Ably } /** - * @function Join + * @function join * @description join realtime room * @returns {void} * @param joinProperties @@ -266,7 +266,7 @@ export default class AblyRealtimeService extends RealtimeService implements Ably public setSyncProperty(name: string, property: T): void { const queue = this.clientSyncPropertiesQueue[name] ?? []; - // clousure to create the event + // closure to create the event const createEvent = (name: string, data: T): RealtimeMessage => { return { name, @@ -659,6 +659,7 @@ export default class AblyRealtimeService extends RealtimeService implements Ably if (KICK_PARTICIPANTS_TIMEOUT) { clearTimeout(KICK_PARTICIPANTS_TIMEOUT); + this.hostAvailabilityObserver.publish(true); } const oldHostParticipantId = this.hostParticipantId; @@ -840,6 +841,7 @@ export default class AblyRealtimeService extends RealtimeService implements Ably // no proper host candidate, kick everyone if (this.shouldKickParticipantsOnHostLeave && hostCandidates.length === 0) { + this.hostAvailabilityObserver.publish(false); KICK_PARTICIPANTS_TIMEOUT = setTimeout(() => { this.kickAllParticipantsObserver.publish(true); }, KICK_PARTICIPANTS_TIME); diff --git a/src/services/realtime/base/index.ts b/src/services/realtime/base/index.ts index b6535db2..b49d48d5 100644 --- a/src/services/realtime/base/index.ts +++ b/src/services/realtime/base/index.ts @@ -12,6 +12,7 @@ export class RealtimeService implements DefaultRealtimeService { public roomInfoUpdatedObserver: Observer; public roomListUpdatedObserver: Observer; public hostObserver: Observer; + public hostAvailabilityObserver: Observer; public realtimeStateObserver: Observer; public syncPropertiesObserver: Observer; public kickAllParticipantsObserver: Observer; @@ -26,10 +27,11 @@ export class RealtimeService implements DefaultRealtimeService { this.syncPropertiesObserver = new Observer({ logger }); this.reconnectObserver = new Observer({ logger }); - // Room info obervers helpers + // Room info observers helpers this.roomInfoUpdatedObserver = new Observer({ logger }); this.roomListUpdatedObserver = new Observer({ logger }); this.hostObserver = new Observer({ logger }); + this.hostAvailabilityObserver = new Observer({ logger }); this.realtimeStateObserver = new Observer({ logger }); this.kickAllParticipantsObserver = new Observer({ logger }); this.authenticationObserver = new Observer({ logger }); @@ -64,7 +66,7 @@ export class RealtimeService implements DefaultRealtimeService { } /** - * @function getParticipantColor + * @function getSlotColor * @description get slot color string * @returns {string} * @param slotIndex From fa4f6f5d54eced22321244cbdf827fb394cb3630 Mon Sep 17 00:00:00 2001 From: Bruno Tutrut Date: Fri, 11 Aug 2023 08:58:12 -0300 Subject: [PATCH 2/2] fix: remove kick participants timeout when has host available in room --- src/services/realtime/ably/index.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/services/realtime/ably/index.ts b/src/services/realtime/ably/index.ts index 8047f110..5b5fc858 100644 --- a/src/services/realtime/ably/index.ts +++ b/src/services/realtime/ably/index.ts @@ -514,6 +514,7 @@ export default class AblyRealtimeService extends RealtimeService implements Ably this.roomInfoUpdatedObserver.publish(this.localRoomProperties); if (!data.hostClientId) { + this.hostParticipantId = null; this.hostPassingHandle(); } else if (data?.hostClientId !== this.hostParticipantId) { this.updateHostInfo(data.hostClientId); @@ -1027,11 +1028,16 @@ export default class AblyRealtimeService extends RealtimeService implements Ably if (!this.localRoomProperties) { this.initializeRoomProperties(); } else { - await Promise.all([ - this.updateParticipants(), - this.localRoomProperties?.hostClientId && - this.updateHostInfo(this.localRoomProperties.hostClientId), - ]); + this.updateParticipants(); + + const isHostCandidate = this.myParticipant.data.type === ParticipantType.HOST; + + if (this.localRoomProperties?.hostClientId) { + await this.updateHostInfo(this.localRoomProperties.hostClientId); + } else if (isHostCandidate) { + await this.setHost(this.myParticipant.data.participantId); + } + this.localRoomProperties = await this.fetchRoomProperties(); this.updateLocalRoomState(this.localRoomProperties); }