22 branches 3 (#13181)

This PR does not produce any functional changes for our users. It
prepares the branches for workflows by:

- decommissioning `output` and `context` fields or `workflowRun` records
and use newly created `state` field from front-end and back-end
- use `stepStatus` computed by `back-end` in `front-end`
- add utils and types in `twenty-shared/workflow` (not completed, a
follow-up is scheduled
https://github.com/twentyhq/core-team-issues/issues/1211)
- add concurrency to `workflowQueue` message queue to avoid weird branch
execution when using forms in workflow branches
- add a WithLock decorator for better dev experience of
`CacheLockService.withLock` usage

Here is an example of such a workflow running (front branch display is
not yet done that's why it looks ugly) ->
https://discord.com/channels/1130383047699738754/1258024460238192691/1392897615171158098
This commit is contained in:
martmull
2025-07-16 11:16:04 +02:00
committed by GitHub
parent bf6330469b
commit 47386e92a3
47 changed files with 5124 additions and 6380 deletions
@@ -1,27 +1,7 @@
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
import { WorkflowDiagramStepNodeIcon } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeIcon';
import {
WorkflowDiagramRunStatus,
WorkflowDiagramStepNodeData,
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import { WorkflowDiagramNodeVariant } from '@/workflow/workflow-diagram/types/WorkflowDiagramNodeVariant';
const getNodeVariantFromRunStatus = (
runStatus: WorkflowDiagramRunStatus | undefined,
): WorkflowDiagramNodeVariant => {
switch (runStatus) {
case 'success':
return 'success';
case 'failure':
return 'failure';
case 'running':
return 'running';
case 'not-executed':
return 'not-executed';
default:
return 'default';
}
};
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import { getNodeVariantFromStepRunStatus } from '@/workflow/workflow-diagram/utils/getNodeVariantFromStepRunStatus';
export const WorkflowDiagramStepNodeReadonly = ({
data,
@@ -31,7 +11,7 @@ export const WorkflowDiagramStepNodeReadonly = ({
return (
<WorkflowDiagramStepNodeBase
name={data.name}
variant={getNodeVariantFromRunStatus(data.runStatus)}
variant={getNodeVariantFromStepRunStatus(data.runStatus)}
nodeType={data.nodeType}
Icon={<WorkflowDiagramStepNodeIcon data={data} />}
/>
@@ -9,7 +9,7 @@ import { useWorkflowVersion } from '@/workflow/hooks/useWorkflowVersion';
import { flowComponentState } from '@/workflow/states/flowComponentState';
import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState';
import { workflowVisualizerWorkflowRunIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowRunIdComponentState';
import { WorkflowRunOutput } from '@/workflow/types/Workflow';
import { WorkflowRunState } from '@/workflow/types/Workflow';
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
import { workflowDiagramStatusComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramStatusComponentState';
import { workflowRunDiagramAutomaticallyOpenedStepsComponentState } from '@/workflow/workflow-diagram/states/workflowRunDiagramAutomaticallyOpenedStepsComponentState';
@@ -82,15 +82,15 @@ export const WorkflowRunVisualizerEffect = ({
const handleWorkflowRunDiagramGeneration = useRecoilCallback(
({ snapshot, set }) =>
({
workflowRunOutput,
workflowRunState,
workflowVersionId,
isInRightDrawer,
}: {
workflowRunOutput: WorkflowRunOutput | undefined;
workflowRunState: WorkflowRunState | undefined;
workflowVersionId: string | undefined;
isInRightDrawer: boolean;
}) => {
if (!(isDefined(workflowRunOutput) && isDefined(workflowVersionId))) {
if (!(isDefined(workflowRunState) && isDefined(workflowVersionId))) {
set(flowState, undefined);
set(workflowDiagramState, undefined);
@@ -108,15 +108,15 @@ export const WorkflowRunVisualizerEffect = ({
set(flowState, {
workflowVersionId,
trigger: workflowRunOutput.flow.trigger,
steps: workflowRunOutput.flow.steps,
trigger: workflowRunState.flow.trigger,
steps: workflowRunState.flow.steps,
});
const { diagram: baseWorkflowRunDiagram, stepToOpenByDefault } =
generateWorkflowRunDiagram({
trigger: workflowRunOutput.flow.trigger,
steps: workflowRunOutput.flow.steps,
stepsOutput: workflowRunOutput.stepsOutput,
trigger: workflowRunState.flow.trigger,
steps: workflowRunState.flow.steps,
stepInfos: workflowRunState.stepInfos,
});
if (isDefined(stepToOpenByDefault)) {
@@ -197,14 +197,14 @@ export const WorkflowRunVisualizerEffect = ({
useEffect(() => {
handleWorkflowRunDiagramGeneration({
workflowRunOutput: workflowRun?.output ?? undefined,
workflowRunState: workflowRun?.state ?? undefined,
workflowVersionId: workflowRun?.workflowVersionId,
isInRightDrawer,
});
}, [
handleWorkflowRunDiagramGeneration,
isInRightDrawer,
workflowRun?.output,
workflowRun?.state,
workflowRun?.workflowVersionId,
]);