Skip to content

Commit 65322b6

Browse files
authored
Simplifies message querying (#574)
To avoid numerous redundant requests from getting re-issued on cache invalidation (all of the "after" requests were getting re-issued, resulting in 10s and even hundreds of requests being issued)
1 parent 546ca5f commit 65322b6

File tree

7 files changed

+27
-125
lines changed

7 files changed

+27
-125
lines changed

workbench-app/src/Constants.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export const Constants = {
2222
return `calc(100vw - ${this.conversationListMinWidth} - ${this.conversationHistoryMinWidth})`;
2323
},
2424
defaultChatWidthPercent: 33,
25-
maxMessagesPerRequest: 500,
2625
maxFileAttachmentsPerMessage: 10,
2726
loaderDelayMs: 100,
2827
responsiveBreakpoints: {

workbench-app/src/components/Conversations/InteractInput.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ export const InteractInput: React.FC<InteractInputProps> = (props) => {
314314
// need to define the extra fields for the message such as sender, timestamp, etc.
315315
// so that the message can be rendered correctly
316316
dispatch(
317-
updateGetConversationMessagesQueryData(conversation.id, [
317+
updateGetConversationMessagesQueryData({ conversationId: conversation.id }, [
318318
...(messages ?? []),
319319
{
320320
id: 'optimistic',

workbench-app/src/libs/useHistoryUtility.ts

Lines changed: 7 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import React from 'react';
2-
import { Constants } from '../Constants';
32
import { ConversationMessage } from '../models/ConversationMessage';
43
import { useAppDispatch } from '../redux/app/hooks';
54
import {
65
conversationApi,
7-
updateGetAllConversationMessagesQueryData,
8-
useGetAllConversationMessagesQuery,
6+
updateGetConversationMessagesQueryData,
7+
useGetConversationMessagesQuery,
98
useGetAssistantsInConversationQuery,
109
useGetConversationFilesQuery,
1110
useGetConversationParticipantsQuery,
1211
useGetConversationQuery,
12+
workbenchApi,
1313
} from '../services/workbench';
1414
import { useGetAssistantCapabilities } from './useAssistantCapabilities';
1515
import { useConversationEvents } from './useConversationEvents';
@@ -27,9 +27,8 @@ export const useHistoryUtility = (conversationId: string) => {
2727
data: allConversationMessages,
2828
error: allConversationMessagesError,
2929
isLoading: allConversationMessagesIsLoading,
30-
} = useGetAllConversationMessagesQuery({
30+
} = useGetConversationMessagesQuery({
3131
conversationId,
32-
limit: Constants.app.maxMessagesPerRequest,
3332
});
3433
const {
3534
data: conversationParticipants,
@@ -72,31 +71,8 @@ export const useHistoryUtility = (conversationId: string) => {
7271

7372
// handler for when a new message is created
7473
const onMessageCreated = React.useCallback(async () => {
75-
if (!allConversationMessages) {
76-
return;
77-
}
78-
79-
const lastMessageId = allConversationMessages[allConversationMessages.length - 1]?.id;
80-
const newMessages = await dispatch(
81-
conversationApi.endpoints.getAllConversationMessages.initiate(
82-
{
83-
conversationId,
84-
limit: Constants.app.maxMessagesPerRequest,
85-
after: lastMessageId,
86-
},
87-
{ forceRefetch: true },
88-
),
89-
).unwrap();
90-
const updatedMessages = [...allConversationMessages, ...newMessages];
91-
92-
// update the cache with the new messages
93-
dispatch(
94-
updateGetAllConversationMessagesQueryData(
95-
{ conversationId, limit: Constants.app.maxMessagesPerRequest },
96-
updatedMessages,
97-
),
98-
);
99-
}, [allConversationMessages, conversationId, dispatch]);
74+
dispatch(workbenchApi.util.invalidateTags(['ConversationMessage']));
75+
}, [dispatch]);
10076

10177
// handler for when a message is deleted
10278
const onMessageDeleted = React.useCallback(
@@ -108,12 +84,7 @@ export const useHistoryUtility = (conversationId: string) => {
10884
const updatedMessages = allConversationMessages.filter((message) => message.id !== messageId);
10985

11086
// remove the message from the messages state
111-
dispatch(
112-
updateGetAllConversationMessagesQueryData(
113-
{ conversationId, limit: Constants.app.maxMessagesPerRequest },
114-
updatedMessages,
115-
),
116-
);
87+
dispatch(updateGetConversationMessagesQueryData({ conversationId }, updatedMessages));
11788
},
11889
[allConversationMessages, conversationId, dispatch],
11990
);

workbench-app/src/libs/useWorkbenchService.ts

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { AssistantServiceInfo } from '../models/AssistantServiceInfo';
77
import { AssistantServiceRegistration } from '../models/AssistantServiceRegistration';
88
import { Conversation } from '../models/Conversation';
99
import { ConversationFile } from '../models/ConversationFile';
10-
import { ConversationMessage } from '../models/ConversationMessage';
1110
import { ConversationParticipant } from '../models/ConversationParticipant';
1211
import { useAppDispatch } from '../redux/app/hooks';
1312
import { addError } from '../redux/features/app/appSlice';
@@ -155,29 +154,11 @@ export const useWorkbenchService = () => {
155154
conversation: Conversation,
156155
participants: ConversationParticipant[],
157156
): Promise<{ blob: Blob; filename: string }> => {
158-
const messages: ConversationMessage[] = [];
159-
let before_message_id: string | undefined = undefined;
160-
161-
while (true) {
162-
try {
163-
const new_messages = await dispatch(
164-
conversationApi.endpoints.getConversationMessages.initiate({
165-
conversationId: conversation.id,
166-
before: before_message_id,
167-
}),
168-
).unwrap();
169-
170-
if (new_messages.length === 0) {
171-
break;
172-
}
173-
174-
messages.unshift(...new_messages);
175-
before_message_id = new_messages[0].id;
176-
} catch (error) {
177-
dispatch(addError({ title: 'Export transcript', message: (error as Error).message }));
178-
throw error;
179-
}
180-
}
157+
const messages = await dispatch(
158+
conversationApi.endpoints.getConversationMessages.initiate({
159+
conversationId: conversation.id,
160+
}),
161+
).unwrap();
181162

182163
const timestampForFilename = Utility.getTimestampForFilename();
183164
const filename = `transcript_${conversation.title.replaceAll(' ', '_')}_${timestampForFilename}.md`;

workbench-app/src/redux/features/app/appSlice.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { generateUuid } from '@azure/ms-rest-js';
44
import { PayloadAction, createSlice } from '@reduxjs/toolkit';
55
import { Constants } from '../../../Constants';
66
import { AppStorage } from '../../../libs/AppStorage';
7-
import { conversationApi } from '../../../services/workbench';
7+
import { workbenchApi } from '../../../services/workbench';
88
import { AppState } from './AppState';
99

1010
const localStorageKey = {
@@ -95,10 +95,7 @@ export const appSlice = createSlice({
9595

9696
// dispatch to invalidate messages cache
9797
if (action.payload) {
98-
conversationApi.endpoints.getConversationMessages.initiate(
99-
{ conversationId: action.payload },
100-
{ forceRefetch: true },
101-
);
98+
workbenchApi.util.invalidateTags(['ConversationMessage']);
10299
}
103100
},
104101
setGlobalContentOpen: (state: AppState, action: PayloadAction<boolean>) => {

workbench-app/src/services/workbench/conversation.ts

Lines changed: 11 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,6 @@ interface GetConversationMessagesProps {
99
messageTypes?: string[];
1010
participantRoles?: string[];
1111
participantIds?: string[];
12-
before?: string;
13-
after?: string;
14-
limit?: number;
1512
}
1613

1714
export const conversationApi = workbenchApi.injectEndpoints({
@@ -62,74 +59,34 @@ export const conversationApi = workbenchApi.injectEndpoints({
6259
transformResponse: (response: any) => transformResponseToConversation(response),
6360
}),
6461
getConversationMessages: builder.query<ConversationMessage[], GetConversationMessagesProps>({
65-
query: ({
66-
conversationId,
67-
messageTypes = ['chat', 'log', 'note', 'notice', 'command', 'command-response'],
68-
participantRoles,
69-
participantIds,
70-
before,
71-
after,
72-
limit,
73-
}) => {
74-
const params = new URLSearchParams();
75-
76-
// Append parameters to the query string, one by one for arrays
77-
messageTypes?.forEach((type) => params.append('message_type', type));
78-
participantRoles?.forEach((role) => params.append('participant_role', role));
79-
participantIds?.forEach((id) => params.append('participant_id', id));
80-
81-
if (before) {
82-
params.set('before', before);
83-
}
84-
if (after) {
85-
params.set('after', after);
86-
}
87-
// Ensure limit does not exceed 500
88-
if (limit !== undefined) {
89-
params.set('limit', String(Math.min(limit, 500)));
90-
}
91-
92-
return `/conversations/${conversationId}/messages?${params.toString()}`;
93-
},
94-
providesTags: ['Conversation'],
95-
transformResponse: (response: any) => transformResponseToConversationMessages(response),
96-
}),
97-
getAllConversationMessages: builder.query<ConversationMessage[], GetConversationMessagesProps>({
9862
async queryFn(
9963
{
10064
conversationId,
10165
messageTypes = ['chat', 'log', 'note', 'notice', 'command', 'command-response'],
10266
participantRoles,
10367
participantIds,
104-
before,
105-
after,
106-
limit,
10768
},
10869
_queryApi,
10970
_extraOptions,
11071
fetchWithBQ,
11172
) {
11273
let allMessages: ConversationMessage[] = [];
113-
let updatedBefore = before;
74+
let before = undefined;
11475

11576
while (true) {
11677
const params = new URLSearchParams();
11778

79+
if (before) {
80+
params.set('before', before);
81+
}
82+
11883
// Append parameters to the query string, one by one for arrays
11984
messageTypes?.forEach((type) => params.append('message_type', type));
12085
participantRoles?.forEach((role) => params.append('participant_role', role));
12186
participantIds?.forEach((id) => params.append('participant_id', id));
12287

123-
if (updatedBefore) {
124-
params.set('before', updatedBefore);
125-
}
126-
if (after) {
127-
params.set('after', after);
128-
}
129-
// Ensure limit does not exceed 500
130-
if (limit !== undefined) {
131-
params.set('limit', String(Math.min(limit, 500)));
132-
}
88+
const limit = 500;
89+
params.set('limit', String(limit));
13390

13491
const url = `/conversations/${conversationId}/messages?${params.toString()}`;
13592

@@ -145,12 +102,12 @@ export const conversationApi = workbenchApi.injectEndpoints({
145102
break;
146103
}
147104

148-
updatedBefore = messages[0].id;
105+
before = messages[0].id;
149106
}
150107

151108
return { data: allMessages };
152109
},
153-
providesTags: ['Conversation'],
110+
providesTags: ['Conversation', 'ConversationMessage'],
154111
}),
155112
getConversationMessageDebugData: builder.query<
156113
ConversationMessageDebug,
@@ -186,9 +143,6 @@ export const conversationApi = workbenchApi.injectEndpoints({
186143

187144
// Non-hook helpers
188145

189-
export const updateGetConversationMessagesQueryData = (conversationId: string, data: ConversationMessage[]) =>
190-
conversationApi.util.updateQueryData('getConversationMessages', { conversationId }, () => data);
191-
192146
export const {
193147
useCreateConversationMutation,
194148
useDuplicateConversationMutation,
@@ -197,16 +151,15 @@ export const {
197151
useGetAssistantConversationsQuery,
198152
useGetConversationQuery,
199153
useGetConversationMessagesQuery,
200-
useGetAllConversationMessagesQuery,
201154
useGetConversationMessageDebugDataQuery,
202155
useCreateConversationMessageMutation,
203156
useDeleteConversationMessageMutation,
204157
} = conversationApi;
205158

206-
export const updateGetAllConversationMessagesQueryData = (
159+
export const updateGetConversationMessagesQueryData = (
207160
options: GetConversationMessagesProps,
208161
messages: ConversationMessage[],
209-
) => conversationApi.util.updateQueryData('getAllConversationMessages', options, () => messages);
162+
) => conversationApi.util.updateQueryData('getConversationMessages', options, () => messages);
210163

211164
const transformConversationForRequest = (conversation: Partial<Conversation>) => ({
212165
id: conversation.id,

workbench-app/src/services/workbench/workbench.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export const workbenchApi = createApi({
7171
'ConversationShare',
7272
'Config',
7373
'State',
74+
'ConversationMessage',
7475
],
7576
endpoints: () => ({}),
7677
});

0 commit comments

Comments
 (0)