Skip to content
This repository was archived by the owner on Jul 3, 2023. It is now read-only.

Commit 713e35c

Browse files
committed
Fix project query mutate.
We properly update the query cache after a mutation. This helps avoid races where client serves stale data after we invalidate the query.
1 parent 8b577f2 commit 713e35c

File tree

2 files changed

+78
-11
lines changed

2 files changed

+78
-11
lines changed

web-ui/src/analytics/editor.tsx

+14-9
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { ProjectDescr } from 'src/types/manager/models/ProjectDescr'
3131
import CompileIndicator from './CompileIndicator'
3232
import SaveIndicator, { SaveIndicatorState } from 'src/components/SaveIndicator'
3333
import { PLACEHOLDER_VALUES } from 'src/utils'
34+
import { projectQueryCacheUpdate } from 'src/types/defaultQueryFn'
3435

3536
// How many ms to wait until we save the project.
3637
const SAVE_DELAY = 2000
@@ -248,20 +249,24 @@ const useUpdateProjectIfChanged = (
248249
)
249250
useEffect(() => {
250251
if (project.project_id !== null && state === 'isModified' && !isLoading) {
252+
const updateRequest = {
253+
project_id: project.project_id,
254+
name: project.name,
255+
description: project.description,
256+
code: project.code
257+
}
251258
mutate(
259+
updateRequest,
252260
{
253-
project_id: project.project_id,
254-
name: project.name,
255-
description: project.description,
256-
code: project.code
257-
},
258-
{
259-
onSuccess: (data: UpdateProjectResponse) => {
260-
setProject((prevState: ProgramState) => ({ ...prevState, version: data.version }))
261-
setState('isUpToDate')
261+
onSettled: () => {
262262
queryClient.invalidateQueries(['project'])
263263
queryClient.invalidateQueries(['projectCode', { project_id: project.project_id }])
264264
queryClient.invalidateQueries(['projectStatus', { project_id: project.project_id }])
265+
},
266+
onSuccess: (data: UpdateProjectResponse) => {
267+
projectQueryCacheUpdate(queryClient, updateRequest)
268+
setProject((prevState: ProgramState) => ({ ...prevState, version: data.version }))
269+
setState('isUpToDate')
265270
setFormError({})
266271
},
267272
onError: (error: CancelError) => {

web-ui/src/types/defaultQueryFn.ts

+64-2
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,72 @@
88
// no queryFn is provided (ideally we never provide a queryFn to reduce
99
// duplication and bugs but always rely on defaultQueryFn to route to the correct API call)
1010

11-
import { QueryFunctionContext } from '@tanstack/react-query'
11+
import { QueryClient, QueryFunctionContext } from '@tanstack/react-query'
1212
import { match, P } from 'ts-pattern'
13+
import {
14+
ConfigService,
15+
ConnectorService,
16+
PipelineService,
17+
ProjectCodeResponse,
18+
ProjectDescr,
19+
ProjectService,
20+
UpdateProjectRequest
21+
} from './manager'
1322

14-
import { ConfigService, ConnectorService, PipelineService, ProjectService } from './manager'
23+
// Updates the query cache for a `UpdateProjectRequest` response.
24+
export const projectQueryCacheUpdate = (queryClient: QueryClient, newData: UpdateProjectRequest) => {
25+
queryClient.setQueryData(
26+
['projectCode', { project_id: newData.project_id }],
27+
(oldData: ProjectCodeResponse | undefined) => {
28+
if (oldData) {
29+
const newd = {
30+
...oldData,
31+
...{
32+
project: {
33+
...oldData.project,
34+
...{
35+
name: newData.name,
36+
description: newData.description ? newData.description : oldData.project.description
37+
},
38+
},
39+
code: newData.code ? newData.code : oldData.code
40+
}
41+
};
42+
console.log('newdata is')
43+
console.log(newd);
44+
return newd
45+
} else {
46+
return oldData
47+
}
48+
}
49+
)
50+
51+
queryClient.setQueryData(
52+
['projectStatus', { project_id: newData.project_id }],
53+
(oldData: ProjectDescr | undefined) => {
54+
return oldData
55+
? {
56+
...oldData,
57+
...{ name: newData.name, description: newData.description ? newData.description : oldData.description }
58+
}
59+
: oldData
60+
}
61+
)
62+
63+
queryClient.setQueryData(['project'], (oldData: ProjectDescr[] | undefined) =>
64+
oldData?.map((project: ProjectDescr) => {
65+
if (project.project_id === newData.project_id) {
66+
const projectDescUpdates = {
67+
name: newData.name,
68+
description: newData.description ? newData.description : project.description
69+
}
70+
return { ...project, ...projectDescUpdates }
71+
} else {
72+
return project
73+
}
74+
})
75+
)
76+
}
1577

1678
export const defaultQueryFn = async (context: QueryFunctionContext) => {
1779
return match(context.queryKey)

0 commit comments

Comments
 (0)