From e8fbbeaec43baabeb7da16bbc02dfeed4896f4b8 Mon Sep 17 00:00:00 2001 From: Gavin Barron Date: Fri, 17 Nov 2023 10:02:00 -0800 Subject: [PATCH] fix: sessionId management (#2862) moves sessionId to be held in sessionStorage to provide a stable id for the lifetime of the browser tab --- .../statefulClient/GraphNotificationClient.ts | 4 +- .../src/statefulClient/useGraphChatClient.ts | 42 ++++++++++++++++--- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts b/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts index bf359c2c77..e27870989c 100644 --- a/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts +++ b/packages/mgt-chat/src/statefulClient/GraphNotificationClient.ts @@ -369,8 +369,8 @@ export class GraphNotificationClient { } public async subscribeToChatNotifications(chatId: string, sessionId: string) { - // if we have a "previous" chat state at present, unsubscribe - if (this.chatId && this.sessionId && chatId !== this.chatId && sessionId !== this.sessionId) { + // if we have a "previous" chat state at present, unsubscribe for the previous chatId + if (this.chatId && this.sessionId && chatId !== this.chatId) { await this.unsubscribeFromChatNotifications(this.chatId, this.sessionId); } this.chatId = chatId; diff --git a/packages/mgt-chat/src/statefulClient/useGraphChatClient.ts b/packages/mgt-chat/src/statefulClient/useGraphChatClient.ts index 08f377caf2..98852ebc44 100644 --- a/packages/mgt-chat/src/statefulClient/useGraphChatClient.ts +++ b/packages/mgt-chat/src/statefulClient/useGraphChatClient.ts @@ -10,13 +10,45 @@ import { v4 as uuid } from 'uuid'; import { StatefulGraphChatClient } from './StatefulGraphChatClient'; import { log } from '@microsoft/mgt-element'; +/** + * The key name to use for storing the sessionId in session storage + */ +const keyName = 'mgt-chat-session-id'; + +/** + * reads a string from session storage, or if there is no string for the keyName, generate a new uuid and place in storage + */ +const getOrGenerateSessionId = () => { + const value = sessionStorage.getItem(keyName); + + if (value) { + return value; + } else { + const newValue = uuid(); + sessionStorage.setItem(keyName, newValue); + return newValue; + } +}; + +/** + * Provides a stable sessionId for the lifetime of the browser tab. + * @returns a string that is either read from session storage or generated and placed in session storage + */ +const useSessionId = (): string => { + // when a function is passed to useState, it is only invoked on the first render + const [sessionId] = useState(getOrGenerateSessionId); + + return sessionId; +}; + +/** + * Custom hook to abstract the creation of a stateful graph chat client. + * @param {string} chatId the current chatId to be rendered + * @returns {StatefulGraphChatClient} a stateful graph chat client that is subscribed to the given chatId + */ export const useGraphChatClient = (chatId: string): StatefulGraphChatClient => { - const [sessionId, setSessionId] = useState(); + const sessionId = useSessionId(); const [chatClient] = useState(() => new StatefulGraphChatClient()); - // generate a new sessionId when the chatId changes - useEffect(() => { - setSessionId(uuid()); - }, [chatId]); // when chatId or sessionId changes this effect subscribes or unsubscribes // the component to/from web socket based notifications for the given chatId