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
@@ -4,7 +4,6 @@ import { commandMenuWorkflowRunIdComponentState } from '@/command-menu/pages/wor
import { commandMenuWorkflowVersionIdComponentState } from '@/command-menu/pages/workflow/states/commandMenuWorkflowVersionIdComponentState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { useSetInitialWorkflowRunRightDrawerTab } from '@/workflow/workflow-diagram/hooks/useSetInitialWorkflowRunRightDrawerTab';
import { WorkflowDiagramRunStatus } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import { t } from '@lingui/core/macro';
import { useRecoilCallback } from 'recoil';
import {
@@ -13,6 +12,7 @@ import {
IconSettingsAutomation,
} from 'twenty-ui/display';
import { v4 } from 'uuid';
import { WorkflowRunStepStatus } from '@/workflow/types/Workflow';
export const useWorkflowCommandMenu = () => {
const { navigateCommandMenu } = useNavigateCommandMenu();
@@ -142,7 +142,7 @@ export const useWorkflowCommandMenu = () => {
title: string;
icon: IconComponent;
workflowSelectedNode: string;
stepExecutionStatus: WorkflowDiagramRunStatus;
stepExecutionStatus: WorkflowRunStepStatus;
}) => {
const pageId = v4();
@@ -20,11 +20,11 @@ import {
WorkflowRunTabId,
WorkflowRunTabIdType,
} from '@/workflow/workflow-steps/types/WorkflowRunTabId';
import { getWorkflowRunStepExecutionStatus } from '@/workflow/workflow-steps/utils/getWorkflowRunStepExecutionStatus';
import styled from '@emotion/styled';
import { isNull } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { IconLogin2, IconLogout, IconStepInto } from 'twenty-ui/display';
import { getWorkflowRunStepExecutionStatus } from '@/workflow/workflow-steps/utils/getWorkflowRunStepExecutionStatus';
const StyledContainer = styled.div`
display: flex;
@@ -65,9 +65,10 @@ export const CommandMenuWorkflowRunViewStepContent = () => {
}
const stepExecutionStatus = getWorkflowRunStepExecutionStatus({
workflowRunOutput: workflowRun.output,
workflowRunState: workflowRun.state,
stepId: workflowSelectedNode,
});
const stepDefinition = getStepDefinitionOrThrow({
stepId: workflowSelectedNode,
trigger: flow.trigger,
@@ -1,15 +1,15 @@
import { WorkflowDiagramRunStatus } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId';
import { WorkflowRunStepStatus } from '@/workflow/types/Workflow';
export const getIsInputTabDisabled = ({
stepExecutionStatus,
workflowSelectedNode,
}: {
workflowSelectedNode: string;
stepExecutionStatus: WorkflowDiagramRunStatus;
stepExecutionStatus: WorkflowRunStepStatus;
}) => {
return (
workflowSelectedNode === TRIGGER_STEP_ID ||
stepExecutionStatus === 'not-executed'
stepExecutionStatus === 'NOT_STARTED'
);
};
@@ -1,11 +1,11 @@
import { WorkflowDiagramRunStatus } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import { WorkflowRunStepStatus } from '@/workflow/types/Workflow';
export const getIsOutputTabDisabled = ({
stepExecutionStatus,
}: {
stepExecutionStatus: WorkflowDiagramRunStatus;
stepExecutionStatus: WorkflowRunStepStatus;
}) => {
return (
stepExecutionStatus === 'running' || stepExecutionStatus === 'not-executed'
stepExecutionStatus === 'RUNNING' || stepExecutionStatus === 'NOT_STARTED'
);
};
@@ -1,12 +1,14 @@
import { WorkflowActionType } from '@/workflow/types/Workflow';
import { WorkflowDiagramRunStatus } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
import {
WorkflowActionType,
WorkflowRunStepStatus,
} from '@/workflow/types/Workflow';
export const getShouldFocusNodeTab = ({
stepExecutionStatus,
actionType,
}: {
stepExecutionStatus: WorkflowDiagramRunStatus;
stepExecutionStatus: WorkflowRunStepStatus;
actionType: WorkflowActionType | undefined;
}) => {
return actionType === 'FORM' && stepExecutionStatus === 'running';
return actionType === 'FORM' && stepExecutionStatus === 'PENDING';
};