Fix issues with Apollo cache in workflow module (#7569)

Fixes #7523
This commit is contained in:
Baptiste Devessier
2024-10-11 15:26:25 +02:00
committed by GitHub
parent 3761fbf86f
commit 521dd04d56
7 changed files with 77 additions and 66 deletions

View File

@ -1,13 +1,11 @@
import { ApolloCache, StoreObject } from '@apollo/client'; import { ApolloCache, StoreObject } from '@apollo/client';
import { triggerUpdateRelationsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect'; import { triggerUpdateRelationsOptimisticEffect } from '@/apollo/optimistic-effect/utils/triggerUpdateRelationsOptimisticEffect';
import { CachedObjectRecordQueryVariables } from '@/apollo/types/CachedObjectRecordQueryVariables';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { RecordGqlRefEdge } from '@/object-record/cache/types/RecordGqlRefEdge'; import { RecordGqlRefEdge } from '@/object-record/cache/types/RecordGqlRefEdge';
import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs'; import { isObjectRecordConnectionWithRefs } from '@/object-record/cache/utils/isObjectRecordConnectionWithRefs';
import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode'; import { RecordGqlNode } from '@/object-record/graphql/types/RecordGqlNode';
import { isDefined } from '~/utils/isDefined'; import { isDefined } from '~/utils/isDefined';
import { parseApolloStoreFieldName } from '~/utils/parseApolloStoreFieldName';
export const triggerDeleteRecordsOptimisticEffect = ({ export const triggerDeleteRecordsOptimisticEffect = ({
cache, cache,
@ -24,7 +22,7 @@ export const triggerDeleteRecordsOptimisticEffect = ({
fields: { fields: {
[objectMetadataItem.namePlural]: ( [objectMetadataItem.namePlural]: (
rootQueryCachedResponse, rootQueryCachedResponse,
{ DELETE, readField, storeFieldName }, { readField },
) => { ) => {
const rootQueryCachedResponseIsNotACachedObjectRecordConnection = const rootQueryCachedResponseIsNotACachedObjectRecordConnection =
!isObjectRecordConnectionWithRefs( !isObjectRecordConnectionWithRefs(
@ -38,11 +36,6 @@ export const triggerDeleteRecordsOptimisticEffect = ({
const rootQueryCachedObjectRecordConnection = rootQueryCachedResponse; const rootQueryCachedObjectRecordConnection = rootQueryCachedResponse;
const { fieldVariables: rootQueryVariables } =
parseApolloStoreFieldName<CachedObjectRecordQueryVariables>(
storeFieldName,
);
const recordIdsToDelete = recordsToDelete.map(({ id }) => id); const recordIdsToDelete = recordsToDelete.map(({ id }) => id);
const cachedEdges = readField<RecordGqlRefEdge[]>( const cachedEdges = readField<RecordGqlRefEdge[]>(
@ -65,14 +58,6 @@ export const triggerDeleteRecordsOptimisticEffect = ({
if (nextCachedEdges.length === cachedEdges?.length) if (nextCachedEdges.length === cachedEdges?.length)
return rootQueryCachedObjectRecordConnection; return rootQueryCachedObjectRecordConnection;
// TODO: same as in update, should we trigger DELETE ?
if (
isDefined(rootQueryVariables?.first) &&
cachedEdges?.length === rootQueryVariables.first
) {
return DELETE;
}
return { return {
...rootQueryCachedObjectRecordConnection, ...rootQueryCachedObjectRecordConnection,
edges: nextCachedEdges, edges: nextCachedEdges,

View File

@ -50,7 +50,6 @@ export const RecordShowPageWorkflowHeader = ({
); );
return deleteOneWorkflowVersion({ return deleteOneWorkflowVersion({
workflowId: workflowWithCurrentVersion.id,
workflowVersionId: workflowWithCurrentVersion.currentVersion.id, workflowVersionId: workflowWithCurrentVersion.currentVersion.id,
}); });
}} }}
@ -69,9 +68,10 @@ export const RecordShowPageWorkflowHeader = ({
workflowWithCurrentVersion, workflowWithCurrentVersion,
); );
return activateWorkflowVersion( return activateWorkflowVersion({
workflowWithCurrentVersion.currentVersion.id, workflowVersionId: workflowWithCurrentVersion.currentVersion.id,
); workflowId: workflowWithCurrentVersion.id,
});
}} }}
/> />
) : workflowWithCurrentVersion?.currentVersion?.status === 'ACTIVE' ? ( ) : workflowWithCurrentVersion?.currentVersion?.status === 'ACTIVE' ? (

View File

@ -108,7 +108,10 @@ export const RecordShowPageWorkflowVersionHeader = ({
Icon={IconPower} Icon={IconPower}
disabled={isWaitingForWorkflowVersion} disabled={isWaitingForWorkflowVersion}
onClick={() => { onClick={() => {
return activateWorkflowVersion(workflowVersion.id); return activateWorkflowVersion({
workflowVersionId: workflowVersion.id,
workflowId: workflowVersion.workflowId,
});
}} }}
/> />
) : workflowVersion?.status === 'ACTIVE' ? ( ) : workflowVersion?.status === 'ACTIVE' ? (

View File

@ -1,18 +1,19 @@
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient'; import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
import { ApolloClient, useApolloClient, useMutation } from '@apollo/client'; import { ApolloClient, useApolloClient, useMutation } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery'; import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache';
import { ACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/activateWorkflowVersion'; import { ACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/activateWorkflowVersion';
import { WorkflowVersion } from '@/workflow/types/Workflow';
import { import {
ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutation,
ActivateWorkflowVersionMutationVariables, ActivateWorkflowVersionMutationVariables,
} from '~/generated/graphql'; } from '~/generated/graphql';
export const useActivateWorkflowVersion = () => { export const useActivateWorkflowVersion = () => {
const apolloClient = useApolloClient();
const apolloMetadataClient = useApolloMetadataClient(); const apolloMetadataClient = useApolloMetadataClient();
const apolloClient = useApolloClient();
const [mutate] = useMutation< const [mutate] = useMutation<
ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutation,
ActivateWorkflowVersionMutationVariables ActivateWorkflowVersionMutationVariables
@ -20,24 +21,55 @@ export const useActivateWorkflowVersion = () => {
client: apolloMetadataClient ?? ({} as ApolloClient<any>), client: apolloMetadataClient ?? ({} as ApolloClient<any>),
}); });
const { findOneRecordQuery: findOneWorkflowVersionQuery } = const { objectMetadataItem: objectMetadataItemWorkflowVersion } =
useFindOneRecordQuery({ useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.WorkflowVersion, objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
}); });
const activateWorkflowVersion = async (workflowVersionId: string) => { const activateWorkflowVersion = async ({
workflowVersionId,
workflowId,
}: {
workflowVersionId: string;
workflowId: string;
}) => {
await mutate({ await mutate({
variables: { variables: {
workflowVersionId, workflowVersionId,
}, },
}); update: () => {
modifyRecordFromCache({
cache: apolloClient.cache,
recordId: workflowVersionId,
objectMetadataItem: objectMetadataItemWorkflowVersion,
fieldModifiers: {
status: () => 'ACTIVE',
},
});
await apolloClient.query({ const cacheSnapshot = apolloClient.cache.extract();
query: findOneWorkflowVersionQuery, const allWorkflowVersions: Array<WorkflowVersion> = Object.values(
variables: { cacheSnapshot,
objectRecordId: workflowVersionId, ).filter(
(item) =>
item.__typename === 'WorkflowVersion' &&
item.workflowId === workflowId,
);
for (const workflowVersion of allWorkflowVersions) {
apolloClient.cache.modify({
id: apolloClient.cache.identify(workflowVersion),
fields: {
status: () => {
return workflowVersion.id !== workflowVersionId &&
workflowVersion.status === 'ACTIVE'
? 'ARCHIVED'
: workflowVersion.status;
},
},
});
}
}, },
fetchPolicy: 'network-only',
}); });
}; };

View File

@ -1,8 +1,9 @@
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient'; import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
import { ApolloClient, useApolloClient, useMutation } from '@apollo/client'; import { ApolloClient, useApolloClient, useMutation } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery'; import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache';
import { DEACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/deactivateWorkflowVersion'; import { DEACTIVATE_WORKFLOW_VERSION } from '@/workflow/graphql/deactivateWorkflowVersion';
import { import {
ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutation,
@ -10,9 +11,8 @@ import {
} from '~/generated/graphql'; } from '~/generated/graphql';
export const useDeactivateWorkflowVersion = () => { export const useDeactivateWorkflowVersion = () => {
const apolloClient = useApolloClient();
const apolloMetadataClient = useApolloMetadataClient(); const apolloMetadataClient = useApolloMetadataClient();
const apolloClient = useApolloClient();
const [mutate] = useMutation< const [mutate] = useMutation<
ActivateWorkflowVersionMutation, ActivateWorkflowVersionMutation,
ActivateWorkflowVersionMutationVariables ActivateWorkflowVersionMutationVariables
@ -20,8 +20,8 @@ export const useDeactivateWorkflowVersion = () => {
client: apolloMetadataClient ?? ({} as ApolloClient<any>), client: apolloMetadataClient ?? ({} as ApolloClient<any>),
}); });
const { findOneRecordQuery: findOneWorkflowVersionQuery } = const { objectMetadataItem: objectMetadataItemWorkflowVersion } =
useFindOneRecordQuery({ useObjectMetadataItem({
objectNameSingular: CoreObjectNameSingular.WorkflowVersion, objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
}); });
@ -30,14 +30,16 @@ export const useDeactivateWorkflowVersion = () => {
variables: { variables: {
workflowVersionId, workflowVersionId,
}, },
}); update: () => {
modifyRecordFromCache({
await apolloClient.query({ cache: apolloClient.cache,
query: findOneWorkflowVersionQuery, recordId: workflowVersionId,
variables: { objectMetadataItem: objectMetadataItemWorkflowVersion,
objectRecordId: workflowVersionId, fieldModifiers: {
status: () => 'DEACTIVATED',
},
});
}, },
fetchPolicy: 'network-only',
}); });
}; };

View File

@ -1,36 +1,17 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { useFindOneRecordQuery } from '@/object-record/hooks/useFindOneRecordQuery';
import { useApolloClient } from '@apollo/client';
export const useDeleteOneWorkflowVersion = () => { export const useDeleteOneWorkflowVersion = () => {
const apolloClient = useApolloClient();
const { findOneRecordQuery: findOneWorkflowRecordQuery } =
useFindOneRecordQuery({
objectNameSingular: CoreObjectNameSingular.Workflow,
});
const { deleteOneRecord } = useDeleteOneRecord({ const { deleteOneRecord } = useDeleteOneRecord({
objectNameSingular: CoreObjectNameSingular.WorkflowVersion, objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
}); });
const deleteOneWorkflowVersion = async ({ const deleteOneWorkflowVersion = async ({
workflowId,
workflowVersionId, workflowVersionId,
}: { }: {
workflowId: string;
workflowVersionId: string; workflowVersionId: string;
}) => { }) => {
await deleteOneRecord(workflowVersionId); await deleteOneRecord(workflowVersionId);
await apolloClient.query({
query: findOneWorkflowRecordQuery,
variables: {
objectRecordId: workflowId,
},
fetchPolicy: 'network-only',
});
}; };
return { deleteOneWorkflowVersion }; return { deleteOneWorkflowVersion };

View File

@ -41,7 +41,6 @@ export const useWorkflowWithCurrentVersion = (
createdAt: 'DescNullsLast', createdAt: 'DescNullsLast',
}, },
], ],
limit: 1,
skip: !isDefined(workflowId), skip: !isDefined(workflowId),
}); });
@ -50,7 +49,16 @@ export const useWorkflowWithCurrentVersion = (
return undefined; return undefined;
} }
const currentVersion = mostRecentWorkflowVersions?.[0]; const draftVersion = mostRecentWorkflowVersions.find(
(workflowVersion) => workflowVersion.status === 'DRAFT',
);
const latestVersion = mostRecentWorkflowVersions[0];
const currentVersion = draftVersion ?? latestVersion;
if (!isDefined(currentVersion)) {
return undefined;
}
return { return {
...workflow, ...workflow,