Skip to content

Commit d941234

Browse files
wanglamruanyl
authored andcommitted
refactor: update get session to manual call (#26)
Signed-off-by: Lin Wang <wonglam@amazon.com>
1 parent 12f538b commit d941234

File tree

6 files changed

+63
-50
lines changed

6 files changed

+63
-50
lines changed

public/contexts/core_context.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import {
88
useOpenSearchDashboards,
99
} from '../../../../src/plugins/opensearch_dashboards_react/public';
1010
import { AppPluginStartDependencies, SetupDependencies } from '../types';
11+
import { SessionLoadService } from '../services/session_load_service';
1112

1213
export interface AssistantServices extends Required<OpenSearchDashboardsServices> {
1314
setupDeps: SetupDependencies;
1415
startDeps: AppPluginStartDependencies;
16+
sessionLoad: SessionLoadService;
1517
}
1618

1719
export const useCore: () => OpenSearchDashboardsReactContextValue<

public/hooks/use_chat_actions.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,24 @@ export const useChatActions = (): AssistantActions => {
5353
}
5454
};
5555

56-
const loadChat = (sessionId?: string, title?: string) => {
56+
const loadChat = async (sessionId?: string, title?: string) => {
5757
abortControllerRef?.abort();
58+
core.services.sessionLoad.abortController?.abort();
5859
chatContext.setSessionId(sessionId);
5960
chatContext.setTitle(title);
6061
// Chat page will always visible in fullscreen mode, we don't need to change the tab anymore
6162
if (!chatContext.flyoutFullScreen) {
6263
chatContext.setSelectedTabId('chat');
6364
}
6465
chatContext.setFlyoutComponent(null);
65-
if (!sessionId) chatStateDispatch({ type: 'reset' });
66+
if (!sessionId) {
67+
chatStateDispatch({ type: 'reset' });
68+
return;
69+
}
70+
const session = await core.services.sessionLoad.load(sessionId);
71+
if (session) {
72+
chatStateDispatch({ type: 'receive', payload: session.messages });
73+
}
6674
};
6775

6876
const openChatUI = () => {

public/hooks/use_sessions.ts

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,46 +6,10 @@
66
import { useCallback, useEffect, useReducer, useState } from 'react';
77
import { HttpFetchQuery, SavedObjectsFindOptions } from '../../../../src/core/public';
88
import { ASSISTANT_API } from '../../common/constants/llm';
9-
import { ISession, ISessionFindResponse } from '../../common/types/chat_saved_object_attributes';
10-
import { useChatContext } from '../contexts/chat_context';
9+
import { ISessionFindResponse } from '../../common/types/chat_saved_object_attributes';
1110
import { useCore } from '../contexts/core_context';
1211
import { GenericReducer, genericReducer, genericReducerWithAbortController } from './fetch_reducer';
1312

14-
export const useGetSession = () => {
15-
const chatContext = useChatContext();
16-
const core = useCore();
17-
const reducer: GenericReducer<ISession> = genericReducer;
18-
const [state, dispatch] = useReducer(reducer, { loading: false });
19-
const [refreshToggle, setRefreshToggle] = useState(false);
20-
21-
const refresh = useCallback(() => {
22-
setRefreshToggle((flag) => !flag);
23-
}, []);
24-
25-
useEffect(() => {
26-
const abortController = new AbortController();
27-
dispatch({ type: 'request' });
28-
if (!chatContext.sessionId) {
29-
dispatch({ type: 'success', payload: undefined });
30-
return;
31-
}
32-
33-
core.services.http
34-
.get<ISession>(`${ASSISTANT_API.SESSION}/${chatContext.sessionId}`, {
35-
signal: abortController.signal,
36-
})
37-
.then((payload) => dispatch({ type: 'success', payload }))
38-
.catch((error) => dispatch({ type: 'failure', error }));
39-
40-
return () => {
41-
abortController.abort();
42-
};
43-
// refreshToggle is used to force refresh session to get latest data
44-
}, [chatContext.sessionId, refreshToggle]);
45-
46-
return { ...state, refresh };
47-
};
48-
4913
export const useGetSessions = (options: Partial<SavedObjectsFindOptions> = {}) => {
5014
const core = useCore();
5115
const reducer: GenericReducer<ISessionFindResponse> = genericReducer;

public/plugin.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
ContentRenderer,
2222
SetupDependencies,
2323
} from './types';
24+
import { SessionLoadService } from './services/session_load_service';
2425

2526
export const [getCoreStart, setCoreStart] = createGetterSetter<CoreStart>('CoreStart');
2627

@@ -56,6 +57,7 @@ export class AssistantPlugin
5657
...coreStart,
5758
setupDeps,
5859
startDeps,
60+
sessionLoad: new SessionLoadService(coreStart.http),
5961
});
6062
const account = await getAccount();
6163
const username = account.data.user_name;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { BehaviorSubject, from } from 'rxjs';
7+
import { HttpStart } from '../../../../src/core/public';
8+
import { ISession } from '../../common/types/chat_saved_object_attributes';
9+
import { ASSISTANT_API } from '../../common/constants/llm';
10+
11+
export class SessionLoadService {
12+
status$: BehaviorSubject<
13+
'idle' | 'loading' | { status: 'error'; error: Error }
14+
> = new BehaviorSubject<'idle' | 'loading' | { status: 'error'; error: Error }>('idle');
15+
abortController?: AbortController;
16+
17+
constructor(private _http: HttpStart) {}
18+
19+
load = async (sessionId: string) => {
20+
this.abortController?.abort();
21+
this.status$.next('loading');
22+
this.abortController = new AbortController();
23+
try {
24+
return await this._http.get<ISession>(`${ASSISTANT_API.SESSION}/${sessionId}`, {
25+
signal: this.abortController.signal,
26+
});
27+
} catch (error) {
28+
this.status$.next({ status: 'error', error });
29+
} finally {
30+
this.status$.next('idle');
31+
}
32+
};
33+
}

public/tabs/chat/chat_page.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,36 @@
44
*/
55

66
import { EuiFlyoutBody, EuiFlyoutFooter, EuiPage, EuiPageBody, EuiSpacer } from '@elastic/eui';
7-
import React, { useEffect, useState } from 'react';
7+
import React, { useCallback, useState } from 'react';
88
import cs from 'classnames';
99
import { useChatContext } from '../../contexts/chat_context';
1010
import { useChatState } from '../../hooks/use_chat_state';
11-
import { useGetSession } from '../../hooks/use_sessions';
1211
import { ChatPageContent } from './chat_page_content';
1312
import { ChatInputControls } from './controls/chat_input_controls';
13+
import { useObservable } from 'react-use';
14+
import { useCore } from '../../contexts/core_context';
1415

1516
interface ChatPageProps {
1617
className?: string;
1718
}
1819

1920
export const ChatPage: React.FC<ChatPageProps> = (props) => {
21+
const core = useCore();
2022
const chatContext = useChatContext();
2123
const { chatState, chatStateDispatch } = useChatState();
2224
const [showGreetings, setShowGreetings] = useState(false);
23-
const {
24-
data: session,
25-
loading: messagesLoading,
26-
error: messagesLoadingError,
27-
refresh,
28-
} = useGetSession();
25+
const sessionLoadStatus = useObservable(core.services.sessionLoad.status$);
26+
const messagesLoading = sessionLoadStatus === 'loading';
2927

30-
useEffect(() => {
28+
const refresh = useCallback(async () => {
29+
if (!chatContext.sessionId) {
30+
return;
31+
}
32+
const session = await core.services.sessionLoad.load(chatContext.sessionId);
3133
if (session) {
3234
chatStateDispatch({ type: 'receive', payload: session.messages });
3335
}
34-
}, [session]);
36+
}, [chatContext.sessionId, chatStateDispatch]);
3537

3638
return (
3739
<>
@@ -42,7 +44,9 @@ export const ChatPage: React.FC<ChatPageProps> = (props) => {
4244
showGreetings={showGreetings}
4345
setShowGreetings={setShowGreetings}
4446
messagesLoading={messagesLoading}
45-
messagesLoadingError={messagesLoadingError}
47+
messagesLoadingError={
48+
typeof sessionLoadStatus !== 'string' ? sessionLoadStatus?.error : undefined
49+
}
4650
onRefresh={refresh}
4751
/>
4852
</EuiPageBody>

0 commit comments

Comments
 (0)