API: Eliminate race condition in Image Builder API slice
The images table uses the useGetComposesQuery hook to fetch composes and implement pagination. When this query is used, args are provided for the offset and limit and a 'Compose' tag is provided for the query. When a mutation is triggered (causing a POST request to be sent to the `/compose` end point), the 'Compose' tag is invalidated which clears all cached data from useGetComposesQuery hooks, which in turn causes the table to refetch compose information. If invalidating the `Compose` tag causes a refetch before the new compose is available in image-builder, the result does not contain the new compose and the table is not updated to include it. This commit eliminates the race condition by waiting for the query to be fulfilled before invalidating tags (and therefore before refetching the data). All of the above applies equally to the `cloneCompose` mutation, and its race condition has also been eliminated. This commit is loosely inspired by the RTK Query docs section on pessimistic updates: https://redux-toolkit.js.org/rtk-query/usage/manual-cache-updates#pessimistic-updates Typescript complains about the type of the tags. It does not recognize the tag types that are defined in the same enhanceEndpoint() function. For now, we simply ignore the Typescript errors. There is some discussion here: https://github.com/reduxjs/redux-toolkit/issues/1510
This commit is contained in:
parent
c73824cd22
commit
6e018ce7c8
2 changed files with 26 additions and 7 deletions
|
|
@ -593,20 +593,20 @@ const CreateImageWizard = () => {
|
|||
return (
|
||||
<ImageCreator
|
||||
onClose={handleClose}
|
||||
onSubmit={({ values, setIsSaving }) => {
|
||||
onSubmit={async ({ values, setIsSaving }) => {
|
||||
setIsSaving(true);
|
||||
const requests = onSave(values);
|
||||
navigate(resolveRelPath(''));
|
||||
// https://redux-toolkit.js.org/rtk-query/usage/mutations#frequently-used-mutation-hook-return-values
|
||||
// If you want to immediately access the result of a mutation, you need to chain `.unwrap()`
|
||||
// if you actually want the payload or to catch the error.
|
||||
// We do this so we can dispatch the appropriate notification (success or failure).
|
||||
Promise.all(
|
||||
await Promise.all(
|
||||
requests.map((composeRequest) =>
|
||||
composeImage({ composeRequest }).unwrap()
|
||||
)
|
||||
)
|
||||
.then(() => {
|
||||
navigate(resolveRelPath(''));
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'success',
|
||||
|
|
@ -620,6 +620,7 @@ const CreateImageWizard = () => {
|
|||
msg = err.response.data?.errors[0]?.detail;
|
||||
}
|
||||
|
||||
navigate(resolveRelPath(''));
|
||||
dispatch(
|
||||
addNotification({
|
||||
variant: 'danger',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue