From 88bfa69418c9af6d4d5fa5653409615857ff05f9 Mon Sep 17 00:00:00 2001 From: Willie Habimana Date: Thu, 24 Oct 2024 09:11:43 -0700 Subject: [PATCH 1/4] initial commit --- .../framework/presence/api-report/presence.alpha.api.md | 2 +- packages/framework/presence/src/presence.ts | 4 ++-- packages/framework/presence/src/systemWorkspace.ts | 8 ++++---- .../framework/presence/src/test/presenceManager.spec.ts | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/framework/presence/api-report/presence.alpha.api.md b/packages/framework/presence/api-report/presence.alpha.api.md index 46d10df4ce81..47e331d7f265 100644 --- a/packages/framework/presence/api-report/presence.alpha.api.md +++ b/packages/framework/presence/api-report/presence.alpha.api.md @@ -38,9 +38,9 @@ export interface IPresence { // @alpha @sealed export interface ISessionClient { connectionId(): ClientConnectionId; - getStatus(): SessionClientStatus; // (undocumented) readonly sessionId: SpecificSessionClientId; + status(): SessionClientStatus; } // @alpha diff --git a/packages/framework/presence/src/presence.ts b/packages/framework/presence/src/presence.ts index 7e89213bb26c..a85994e6394b 100644 --- a/packages/framework/presence/src/presence.ts +++ b/packages/framework/presence/src/presence.ts @@ -79,7 +79,7 @@ export interface ISessionClient< * @remarks * Connection id will change on reconnect. * - * If {@link ISessionClient.getStatus} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection id. + * If {@link ISessionClient.status} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection id. */ connectionId(): ClientConnectionId; @@ -89,7 +89,7 @@ export interface ISessionClient< * @returns Status of session client. * */ - getStatus(): SessionClientStatus; + status(): SessionClientStatus; } /** diff --git a/packages/framework/presence/src/systemWorkspace.ts b/packages/framework/presence/src/systemWorkspace.ts index 32d63aea9d92..05bffec78bc6 100644 --- a/packages/framework/presence/src/systemWorkspace.ts +++ b/packages/framework/presence/src/systemWorkspace.ts @@ -92,7 +92,7 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { connectionId: () => { throw new Error("Client has never been connected"); }, - getStatus: () => SessionClientStatus.Disconnected, + status: () => SessionClientStatus.Disconnected, }; this.attendees.set(clientSessionId, this.selfAttendee); } @@ -151,7 +151,7 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { }; this.selfAttendee.connectionId = () => clientConnectionId; - this.selfAttendee.getStatus = () => SessionClientStatus.Connected; + this.selfAttendee.status = () => SessionClientStatus.Connected; this.attendees.set(clientConnectionId, this.selfAttendee); } @@ -165,7 +165,7 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { // therefore we should not change the attendee connection status or emit a disconnect event. const attendeeReconnected = attendee.connectionId() !== clientConnectionId; if (!attendeeReconnected) { - attendee.getStatus = () => SessionClientStatus.Disconnected; + attendee.status = () => SessionClientStatus.Disconnected; this.events.emit("attendeeDisconnected", attendee); } } @@ -211,7 +211,7 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { sessionId: clientSessionId, order, connectionId, - getStatus: () => SessionClientStatus.Connected, + status: () => SessionClientStatus.Connected, }; this.attendees.set(clientSessionId, attendee); isNew = true; diff --git a/packages/framework/presence/src/test/presenceManager.spec.ts b/packages/framework/presence/src/test/presenceManager.spec.ts index ccf5821761cf..9d8e859f043c 100644 --- a/packages/framework/presence/src/test/presenceManager.spec.ts +++ b/packages/framework/presence/src/test/presenceManager.spec.ts @@ -176,7 +176,7 @@ describe("Presence", () => { "No attendee was disconnected in beforeEach", ); assert.equal( - disconnectedAttendee.getStatus(), + disconnectedAttendee.status(), SessionClientStatus.Disconnected, "Disconnected attendee has wrong status", ); From 55477c4283697328b8ed0d6505db7e850cb73d7a Mon Sep 17 00:00:00 2001 From: Willie Habimana Date: Thu, 24 Oct 2024 14:58:05 -0700 Subject: [PATCH 2/4] get naming --- .../external-controller/src/view.ts | 2 +- .../presence/api-report/presence.alpha.api.md | 4 ++-- packages/framework/presence/src/baseTypes.ts | 2 +- packages/framework/presence/src/presence.ts | 6 +++--- .../framework/presence/src/systemWorkspace.ts | 20 +++++++++---------- .../presence/src/test/presenceManager.spec.ts | 8 ++++---- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/examples/service-clients/azure-client/external-controller/src/view.ts b/examples/service-clients/azure-client/external-controller/src/view.ts index 8a1938ddf9c8..c3cb1aea37e9 100644 --- a/examples/service-clients/azure-client/external-controller/src/view.ts +++ b/examples/service-clients/azure-client/external-controller/src/view.ts @@ -167,7 +167,7 @@ function makePresenceView( logContentDiv.style.border = "1px solid black"; if (audience !== undefined) { presenceConfig.presence.events.on("attendeeJoined", (attendee) => { - const name = audience.getMembers().get(attendee.connectionId())?.name; + const name = audience.getMembers().get(attendee.getConnectionId())?.name; const update = `client ${name === undefined ? "(unnamed)" : `named ${name}`} with id ${attendee.sessionId} joined`; addLogEntry(logContentDiv, update); }); diff --git a/packages/framework/presence/api-report/presence.alpha.api.md b/packages/framework/presence/api-report/presence.alpha.api.md index 47e331d7f265..6625078460a3 100644 --- a/packages/framework/presence/api-report/presence.alpha.api.md +++ b/packages/framework/presence/api-report/presence.alpha.api.md @@ -37,10 +37,10 @@ export interface IPresence { // @alpha @sealed export interface ISessionClient { - connectionId(): ClientConnectionId; + getConnectionId(): ClientConnectionId; + getStatus(): SessionClientStatus; // (undocumented) readonly sessionId: SpecificSessionClientId; - status(): SessionClientStatus; } // @alpha diff --git a/packages/framework/presence/src/baseTypes.ts b/packages/framework/presence/src/baseTypes.ts index 3f2586f3d6af..6af16c338573 100644 --- a/packages/framework/presence/src/baseTypes.ts +++ b/packages/framework/presence/src/baseTypes.ts @@ -10,7 +10,7 @@ * Each client connection is given a unique identifier for the duration of the * connection. If a client disconnects and reconnects, it will be given a new * identifier. Prefer use of {@link ISessionClient} as a way to identify clients - * in a session. {@link ISessionClient.connectionId} will provide the current + * in a session. {@link ISessionClient.getConnectionId} will provide the current * connection identifier for a logical session client. * * @privateRemarks diff --git a/packages/framework/presence/src/presence.ts b/packages/framework/presence/src/presence.ts index a85994e6394b..202a65cdb9c5 100644 --- a/packages/framework/presence/src/presence.ts +++ b/packages/framework/presence/src/presence.ts @@ -79,9 +79,9 @@ export interface ISessionClient< * @remarks * Connection id will change on reconnect. * - * If {@link ISessionClient.status} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection id. + * If {@link ISessionClient.getStatus} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection id. */ - connectionId(): ClientConnectionId; + getConnectionId(): ClientConnectionId; /** * Get status of session client. @@ -89,7 +89,7 @@ export interface ISessionClient< * @returns Status of session client. * */ - status(): SessionClientStatus; + getStatus(): SessionClientStatus; } /** diff --git a/packages/framework/presence/src/systemWorkspace.ts b/packages/framework/presence/src/systemWorkspace.ts index 05bffec78bc6..2a889def7b8c 100644 --- a/packages/framework/presence/src/systemWorkspace.ts +++ b/packages/framework/presence/src/systemWorkspace.ts @@ -33,7 +33,7 @@ export interface SystemWorkspaceDatastore { /** * There is no implementation class for this interface. * It is a simple structure. Most complicated aspect is that - * `connectionId()` member is replaced with a new + * `getConnectionId()` member is replaced with a new * function when a more recent connection is added. * * See {@link SystemWorkspaceImpl.ensureAttendee}. @@ -89,10 +89,10 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { this.selfAttendee = { sessionId: clientSessionId, order: 0, - connectionId: () => { + getConnectionId: () => { throw new Error("Client has never been connected"); }, - status: () => SessionClientStatus.Disconnected, + getStatus: () => SessionClientStatus.Disconnected, }; this.attendees.set(clientSessionId, this.selfAttendee); } @@ -150,8 +150,8 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { value: this.selfAttendee.sessionId, }; - this.selfAttendee.connectionId = () => clientConnectionId; - this.selfAttendee.status = () => SessionClientStatus.Connected; + this.selfAttendee.getConnectionId = () => clientConnectionId; + this.selfAttendee.getStatus = () => SessionClientStatus.Connected; this.attendees.set(clientConnectionId, this.selfAttendee); } @@ -163,9 +163,9 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { // If the last known connectionID is different from the connection id being removed, the attendee has reconnected, // therefore we should not change the attendee connection status or emit a disconnect event. - const attendeeReconnected = attendee.connectionId() !== clientConnectionId; + const attendeeReconnected = attendee.getConnectionId() !== clientConnectionId; if (!attendeeReconnected) { - attendee.status = () => SessionClientStatus.Disconnected; + attendee.getStatus = () => SessionClientStatus.Disconnected; this.events.emit("attendeeDisconnected", attendee); } } @@ -210,8 +210,8 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { attendee = { sessionId: clientSessionId, order, - connectionId, - status: () => SessionClientStatus.Connected, + getConnectionId: connectionId, + getStatus: () => SessionClientStatus.Connected, }; this.attendees.set(clientSessionId, attendee); isNew = true; @@ -219,7 +219,7 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { // The given association is newer than the one we have. // Update the order and current connection id. attendee.order = order; - attendee.connectionId = connectionId; + attendee.getConnectionId = connectionId; } // Always update entry for the connection id. (Okay if already set.) this.attendees.set(clientConnectionId, attendee); diff --git a/packages/framework/presence/src/test/presenceManager.spec.ts b/packages/framework/presence/src/test/presenceManager.spec.ts index 9d8e859f043c..6e6e26ddce38 100644 --- a/packages/framework/presence/src/test/presenceManager.spec.ts +++ b/packages/framework/presence/src/test/presenceManager.spec.ts @@ -125,7 +125,7 @@ describe("Presence", () => { "Attendee has wrong session id", ); assert.equal( - newAttendee.connectionId(), + newAttendee.getConnectionId(), initialAttendeeConnectionId, "Attendee has wrong client connection id", ); @@ -163,7 +163,7 @@ describe("Presence", () => { "Disconnected attendee has wrong session id", ); assert.equal( - disconnectedAttendee.connectionId(), + disconnectedAttendee.getConnectionId(), initialAttendeeConnectionId, "Disconnected attendee has wrong client connection id", ); @@ -176,7 +176,7 @@ describe("Presence", () => { "No attendee was disconnected in beforeEach", ); assert.equal( - disconnectedAttendee.status(), + disconnectedAttendee.getStatus(), SessionClientStatus.Disconnected, "Disconnected attendee has wrong status", ); @@ -251,7 +251,7 @@ describe("Presence", () => { ); // Current connection id is updated assert( - newAttendee.connectionId() === updatedClientConnectionId, + newAttendee.getConnectionId() === updatedClientConnectionId, "Attendee does not have updated client connection id", ); // Attendee is available via new connection id From c107a4a3a4fe5156422a9701d97d40d5bf0674ac Mon Sep 17 00:00:00 2001 From: Willie Habimana Date: Thu, 31 Oct 2024 13:30:51 -0700 Subject: [PATCH 3/4] first commit --- .../presence/api-report/presence.alpha.api.md | 4 +- packages/framework/presence/src/presence.ts | 18 ++++- .../framework/presence/src/systemWorkspace.ts | 72 ++++++++++--------- .../presence/src/test/presenceManager.spec.ts | 2 +- 4 files changed, 59 insertions(+), 37 deletions(-) diff --git a/packages/framework/presence/api-report/presence.alpha.api.md b/packages/framework/presence/api-report/presence.alpha.api.md index 6625078460a3..484c114b235a 100644 --- a/packages/framework/presence/api-report/presence.alpha.api.md +++ b/packages/framework/presence/api-report/presence.alpha.api.md @@ -38,9 +38,11 @@ export interface IPresence { // @alpha @sealed export interface ISessionClient { getConnectionId(): ClientConnectionId; - getStatus(): SessionClientStatus; + getConnectionStatus(): SessionClientStatus; // (undocumented) readonly sessionId: SpecificSessionClientId; + setConnectionId(connectionId: ClientConnectionId): void; + setConnectionStatus(connected: boolean): void; } // @alpha diff --git a/packages/framework/presence/src/presence.ts b/packages/framework/presence/src/presence.ts index 202a65cdb9c5..4ef9b7256e75 100644 --- a/packages/framework/presence/src/presence.ts +++ b/packages/framework/presence/src/presence.ts @@ -79,7 +79,7 @@ export interface ISessionClient< * @remarks * Connection id will change on reconnect. * - * If {@link ISessionClient.getStatus} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection id. + * If {@link ISessionClient.getConnectionStatus} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection id. */ getConnectionId(): ClientConnectionId; @@ -89,7 +89,21 @@ export interface ISessionClient< * @returns Status of session client. * */ - getStatus(): SessionClientStatus; + getConnectionStatus(): SessionClientStatus; + + /** + * Set current client connection id. + * + * @param connectionId - New connection id. + */ + setConnectionId(connectionId: ClientConnectionId): void; + + /** + * Set status of session client. + * + * @param connected - True if client is connected. + */ + setConnectionStatus(connected: boolean): void; } /** diff --git a/packages/framework/presence/src/systemWorkspace.ts b/packages/framework/presence/src/systemWorkspace.ts index 2a889def7b8c..0a81e721eb2f 100644 --- a/packages/framework/presence/src/systemWorkspace.ts +++ b/packages/framework/presence/src/systemWorkspace.ts @@ -30,20 +30,39 @@ export interface SystemWorkspaceDatastore { }; } -/** - * There is no implementation class for this interface. - * It is a simple structure. Most complicated aspect is that - * `getConnectionId()` member is replaced with a new - * function when a more recent connection is added. - * - * See {@link SystemWorkspaceImpl.ensureAttendee}. - */ -interface SessionClient extends ISessionClient { - /** - * Order is used to track the most recent client connection - * during a session. - */ - order: number; +class SessionClient implements ISessionClient { + public readonly sessionId: ClientSessionId; + public order: number; + private _connectionId: ClientConnectionId | undefined; + private _connectionStatus: SessionClientStatus; + + public constructor(sessionId: ClientSessionId, connectionId?: ClientConnectionId) { + this.sessionId = sessionId; + this.order = 0; + this._connectionId = connectionId; + this._connectionStatus = SessionClientStatus.Disconnected; + } + + public getConnectionId(): ClientConnectionId { + if (this._connectionId === undefined) { + throw new Error("Client has never been connected"); + } + return this._connectionId; + } + + public getConnectionStatus(): SessionClientStatus { + return this._connectionStatus; + } + + public setConnectionId(connectionId: ClientConnectionId): void { + this._connectionId = connectionId; + } + + public setConnectionStatus(connected: boolean): void { + this._connectionStatus = connected + ? SessionClientStatus.Connected + : SessionClientStatus.Disconnected; + } } /** @@ -86,14 +105,7 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { Pick >, ) { - this.selfAttendee = { - sessionId: clientSessionId, - order: 0, - getConnectionId: () => { - throw new Error("Client has never been connected"); - }, - getStatus: () => SessionClientStatus.Disconnected, - }; + this.selfAttendee = new SessionClient(clientSessionId); this.attendees.set(clientSessionId, this.selfAttendee); } @@ -150,8 +162,8 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { value: this.selfAttendee.sessionId, }; - this.selfAttendee.getConnectionId = () => clientConnectionId; - this.selfAttendee.getStatus = () => SessionClientStatus.Connected; + this.selfAttendee.setConnectionId(clientConnectionId); + this.selfAttendee.setConnectionStatus(true); this.attendees.set(clientConnectionId, this.selfAttendee); } @@ -165,7 +177,7 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { // therefore we should not change the attendee connection status or emit a disconnect event. const attendeeReconnected = attendee.getConnectionId() !== clientConnectionId; if (!attendeeReconnected) { - attendee.getStatus = () => SessionClientStatus.Disconnected; + attendee.setConnectionStatus(false); this.events.emit("attendeeDisconnected", attendee); } } @@ -201,25 +213,19 @@ class SystemWorkspaceImpl implements PresenceStatesInternal, SystemWorkspace { clientConnectionId: ClientConnectionId, order: number, ): { attendee: SessionClient; isNew: boolean } { - const connectionId = (): ClientConnectionId => clientConnectionId; let attendee = this.attendees.get(clientSessionId); let isNew = false; if (attendee === undefined) { // New attendee. Create SessionClient and add session id based // entry to map. - attendee = { - sessionId: clientSessionId, - order, - getConnectionId: connectionId, - getStatus: () => SessionClientStatus.Connected, - }; + attendee = new SessionClient(clientSessionId, clientConnectionId); this.attendees.set(clientSessionId, attendee); isNew = true; } else if (order > attendee.order) { // The given association is newer than the one we have. // Update the order and current connection id. attendee.order = order; - attendee.getConnectionId = connectionId; + attendee.setConnectionId(clientConnectionId); } // Always update entry for the connection id. (Okay if already set.) this.attendees.set(clientConnectionId, attendee); diff --git a/packages/framework/presence/src/test/presenceManager.spec.ts b/packages/framework/presence/src/test/presenceManager.spec.ts index 6e6e26ddce38..5fb8c4c62b2f 100644 --- a/packages/framework/presence/src/test/presenceManager.spec.ts +++ b/packages/framework/presence/src/test/presenceManager.spec.ts @@ -176,7 +176,7 @@ describe("Presence", () => { "No attendee was disconnected in beforeEach", ); assert.equal( - disconnectedAttendee.getStatus(), + disconnectedAttendee.getConnectionStatus(), SessionClientStatus.Disconnected, "Disconnected attendee has wrong status", ); From 471c578222429c27097bbf2f7a49d3fec9ab55b7 Mon Sep 17 00:00:00 2001 From: Willie Habimana Date: Thu, 31 Oct 2024 13:32:31 -0700 Subject: [PATCH 4/4] connection status --- packages/framework/presence/src/presence.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/framework/presence/src/presence.ts b/packages/framework/presence/src/presence.ts index 4ef9b7256e75..e10ce3db5c78 100644 --- a/packages/framework/presence/src/presence.ts +++ b/packages/framework/presence/src/presence.ts @@ -84,9 +84,9 @@ export interface ISessionClient< getConnectionId(): ClientConnectionId; /** - * Get status of session client. + * Get connection status of session client. * - * @returns Status of session client. + * @returns Connection status of session client. * */ getConnectionStatus(): SessionClientStatus; @@ -99,7 +99,7 @@ export interface ISessionClient< setConnectionId(connectionId: ClientConnectionId): void; /** - * Set status of session client. + * Set connection status of session client. * * @param connected - True if client is connected. */