Remove useless columns (#13312)

This commit is contained in:
martmull
2025-07-21 20:41:05 +02:00
committed by GitHub
parent 637b1b628a
commit 96daf5555d
19 changed files with 95 additions and 4671 deletions

View File

@ -1,6 +1,6 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { orderWorkflowRunOutput } from '@/object-record/record-field/meta-types/utils/orderWorkflowRunOutput';
import { orderWorkflowRunState } from '@/object-record/record-field/meta-types/utils/orderWorkflowRunState';
import { FieldJsonValue } from '@/object-record/record-field/types/FieldMetadata';
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
@ -15,10 +15,10 @@ export const useFormattedJsonFieldValue = ({
if (
fieldDefinition.metadata.objectMetadataNameSingular ===
CoreObjectNameSingular.WorkflowRun &&
fieldDefinition.metadata.fieldName === 'output' &&
fieldDefinition.metadata.fieldName === 'state' &&
isDefined(fieldValue)
) {
return orderWorkflowRunOutput(fieldValue) as FieldJsonValue;
return orderWorkflowRunState(fieldValue) as FieldJsonValue;
}
return fieldValue;

View File

@ -1,6 +1,6 @@
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
import { orderWorkflowRunOutput } from '@/object-record/record-field/meta-types/utils/orderWorkflowRunOutput';
import { orderWorkflowRunState } from '@/object-record/record-field/meta-types/utils/orderWorkflowRunState';
import { useContext } from 'react';
import { isDefined, parseJson } from 'twenty-shared/utils';
import { JsonObject, JsonValue } from 'type-fest';
@ -19,10 +19,10 @@ export const usePrecomputedJsonDraftValue = ({
if (
fieldDefinition.metadata.objectMetadataNameSingular ===
CoreObjectNameSingular.WorkflowRun &&
fieldDefinition.metadata.fieldName === 'output' &&
fieldDefinition.metadata.fieldName === 'state' &&
isDefined(draftValue)
) {
return orderWorkflowRunOutput(parsedJsonValue) as JsonObject;
return orderWorkflowRunState(parsedJsonValue) as JsonObject;
}
return parsedJsonValue;

View File

@ -10,6 +10,6 @@ export const isWorkflowRunJsonField = ({
}) => {
return (
objectMetadataNameSingular === CoreObjectNameSingular.WorkflowRun &&
(fieldName === 'output' || fieldName === 'context')
fieldName === 'state'
);
};

View File

@ -1,27 +0,0 @@
import { WorkflowRunOutput } from '@/workflow/types/Workflow';
import { workflowRunOutputSchema } from '@/workflow/validation-schemas/workflowSchema';
import { isDefined } from 'twenty-shared/utils';
import { JsonValue } from 'type-fest';
export const orderWorkflowRunOutput = (value: JsonValue) => {
const parsedValue = workflowRunOutputSchema.safeParse(value);
if (!parsedValue.success) {
return null;
}
const orderedWorkflowRunOutput: WorkflowRunOutput = {
...(isDefined(parsedValue.data.error)
? {
error: parsedValue.data.error,
}
: {}),
...(isDefined(parsedValue.data.stepsOutput)
? {
stepsOutput: parsedValue.data.stepsOutput,
}
: {}),
flow: parsedValue.data.flow,
};
return orderedWorkflowRunOutput;
};

View File

@ -0,0 +1,23 @@
import { WorkflowRunState } from '@/workflow/types/Workflow';
import { workflowRunStateSchema } from '@/workflow/validation-schemas/workflowSchema';
import { isDefined } from 'twenty-shared/utils';
import { JsonValue } from 'type-fest';
export const orderWorkflowRunState = (value: JsonValue) => {
const parsedValue = workflowRunStateSchema.safeParse(value);
if (!parsedValue.success) {
return null;
}
const orderedWorkflowRunState: WorkflowRunState = {
...(isDefined(parsedValue.data.workflowRunError)
? {
workflowRunError: parsedValue.data.workflowRunError,
}
: {}),
stepInfos: parsedValue.data.stepInfos,
flow: parsedValue.data.flow,
};
return orderedWorkflowRunState;
};

View File

@ -80,8 +80,6 @@ export const useRunWorkflowVersion = () => {
const recordInput: Partial<WorkflowRun> = {
name: '#0',
status: 'NOT_STARTED',
output: null,
context: null,
workflowVersionId,
workflowId,
createdAt: new Date().toISOString(),

View File

@ -1,63 +1,26 @@
import {
workflowAiAgentActionSchema,
workflowAiAgentActionSettingsSchema,
workflowCodeActionSchema,
workflowCodeActionSettingsSchema,
workflowCreateRecordActionSchema,
workflowCreateRecordActionSettingsSchema,
workflowCronTriggerSchema,
workflowDatabaseEventTriggerSchema,
workflowDeleteRecordActionSchema,
workflowDeleteRecordActionSettingsSchema,
workflowExecutorOutputSchema,
workflowFilterActionSchema,
workflowFilterActionSettingsSchema,
workflowFindRecordsActionSchema,
workflowFindRecordsActionSettingsSchema,
workflowFormActionSchema,
workflowFormActionSettingsSchema,
workflowHttpRequestActionSchema,
workflowManualTriggerSchema,
workflowRunOutputSchema,
workflowRunOutputStepsOutputSchema,
workflowRunSchema,
workflowRunStateSchema,
workflowRunStatusSchema,
workflowRunStepStatusSchema,
workflowSendEmailActionSchema,
workflowSendEmailActionSettingsSchema,
workflowTriggerSchema,
workflowUpdateRecordActionSchema,
workflowUpdateRecordActionSettingsSchema,
workflowWebhookTriggerSchema,
} from '@/workflow/validation-schemas/workflowSchema';
import { z } from 'zod';
export type WorkflowCodeActionSettings = z.infer<
typeof workflowCodeActionSettingsSchema
>;
export type WorkflowSendEmailActionSettings = z.infer<
typeof workflowSendEmailActionSettingsSchema
>;
export type WorkflowCreateRecordActionSettings = z.infer<
typeof workflowCreateRecordActionSettingsSchema
>;
export type WorkflowUpdateRecordActionSettings = z.infer<
typeof workflowUpdateRecordActionSettingsSchema
>;
export type WorkflowDeleteRecordActionSettings = z.infer<
typeof workflowDeleteRecordActionSettingsSchema
>;
export type WorkflowFindRecordsActionSettings = z.infer<
typeof workflowFindRecordsActionSettingsSchema
>;
export type WorkflowFilterActionSettings = z.infer<
typeof workflowFilterActionSettingsSchema
>;
export type WorkflowFormActionSettings = z.infer<
typeof workflowFormActionSettingsSchema
>;
export type WorkflowCodeAction = z.infer<typeof workflowCodeActionSchema>;
export type WorkflowSendEmailAction = z.infer<
typeof workflowSendEmailActionSchema
@ -80,10 +43,6 @@ export type WorkflowHttpRequestAction = z.infer<
typeof workflowHttpRequestActionSchema
>;
export type WorkflowAiAgentActionSettings = z.infer<
typeof workflowAiAgentActionSettingsSchema
>;
export type WorkflowAiAgentAction = z.infer<typeof workflowAiAgentActionSchema>;
export type WorkflowAction =
@ -143,14 +102,6 @@ export type ManualTriggerWorkflowVersion = WorkflowVersion & {
trigger: WorkflowManualTrigger | null;
};
export type WorkflowRunOutput = z.infer<typeof workflowRunOutputSchema>;
export type WorkflowExecutorOutput = z.infer<
typeof workflowExecutorOutputSchema
>;
export type WorkflowRunOutputStepsOutput = z.infer<
typeof workflowRunOutputStepsOutputSchema
>;
export type WorkflowRunStatus = z.infer<typeof workflowRunStatusSchema>;
export type WorkflowRun = z.infer<typeof workflowRunSchema>;

View File

@ -297,27 +297,6 @@ export const workflowTriggerSchema = z.discriminatedUnion('type', [
workflowWebhookTriggerSchema,
]);
// Step output schemas
export const workflowExecutorOutputSchema = z.object({
result: z.any().optional(),
error: z.any().optional(),
pendingEvent: z.boolean().optional(),
});
export const workflowRunOutputStepsOutputSchema = z.record(
workflowExecutorOutputSchema,
);
// Final workflow run output schema
export const workflowRunOutputSchema = z.object({
flow: z.object({
trigger: workflowTriggerSchema,
steps: z.array(workflowActionSchema),
}),
stepsOutput: workflowRunOutputStepsOutputSchema.optional(),
error: z.any().optional(),
});
export const workflowRunStepStatusSchema = z.nativeEnum(StepStatus);
export const workflowRunStateStepInfoSchema = z.object({
@ -339,8 +318,6 @@ export const workflowRunStateSchema = z.object({
workflowRunError: z.any().optional(),
});
export const workflowRunContextSchema = z.record(z.any());
export const workflowRunStatusSchema = z.enum([
'NOT_STARTED',
'RUNNING',
@ -355,8 +332,6 @@ export const workflowRunSchema = z
id: z.string(),
workflowVersionId: z.string(),
workflowId: z.string(),
output: workflowRunOutputSchema.nullable(),
context: workflowRunContextSchema.nullable(),
state: workflowRunStateSchema.nullable(),
status: workflowRunStatusSchema,
createdAt: z.string(),

View File

@ -35,6 +35,8 @@ export const WorkflowRunStepOutputDetail = ({ stepId }: { stepId: string }) => {
const stepInfo = workflowRun.state.stepInfos[stepId];
const { status: _, ...stepInfoWithoutStatus } = stepInfo ?? {};
const stepDefinition = getStepDefinitionOrThrow({
stepId,
trigger: workflowRun.state.flow.trigger,
@ -84,7 +86,7 @@ export const WorkflowRunStepOutputDetail = ({ stepId }: { stepId: string }) => {
<WorkflowRunStepJsonContainer>
<JsonTree
value={stepInfo ?? t`No output available`}
value={stepInfoWithoutStatus ?? t`No output available`}
shouldExpandNodeInitially={isTwoFirstDepths}
emptyArrayLabel={t`Empty Array`}
emptyObjectLabel={t`Empty Object`}

View File

@ -25,8 +25,6 @@ export const useSubmitFormStep = () => {
id: true,
name: true,
status: true,
output: true,
context: true,
startedAt: true,
endedAt: true,
},

File diff suppressed because it is too large Load Diff

View File

@ -95,11 +95,12 @@ export class MigrateWorkflowRunStatesCommand extends ActiveOrSuspendedWorkspaces
? { where: { startedAt: MoreThan(this.afterDate) } }
: {};
const workflowRuns = await workflowRunRepository.find({
const workflowRuns = (await workflowRunRepository.find({
...findOption,
skip: offset * this.chunkSize,
take: this.chunkSize,
});
// eslint-disable-next-line @typescript-eslint/no-explicit-any
})) as any[]; // We type as any as workflowRun output has been removed since 1.1.0 release
for (const workflowRun of workflowRuns) {
const output = workflowRun.output;

View File

@ -0,0 +1,39 @@
import { InjectRepository } from '@nestjs/typeorm';
import { Command } from 'nest-commander';
import { IsNull, Repository } from 'typeorm';
import {
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
RunOnWorkspaceArgs,
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
@Command({
name: 'migrate:1-2:remove-workflow-runs-without-state',
description: 'Remove workflow runs without state.',
})
export class RemoveWorkflowRunsWithoutState extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
constructor(
@InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>,
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
) {
super(workspaceRepository, twentyORMGlobalManager);
}
override async runOnWorkspace({
workspaceId,
}: RunOnWorkspaceArgs): Promise<void> {
const workflowRunRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkflowRunWorkspaceEntity>(
workspaceId,
'workflowRun',
{ shouldBypassPermissionChecks: true },
);
await workflowRunRepository.delete({ state: IsNull() });
}
}

View File

@ -1,8 +1,12 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { RemoveWorkflowRunsWithoutState } from 'src/database/commands/upgrade-version-command/1-2/1-2-remove-workflow-runs-without-state.command';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
@Module({
imports: [],
providers: [],
exports: [],
imports: [TypeOrmModule.forFeature([Workspace], 'core')],
providers: [RemoveWorkflowRunsWithoutState],
exports: [RemoveWorkflowRunsWithoutState],
})
export class V1_2_UpgradeVersionCommandModule {}

View File

@ -31,6 +31,7 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command';
import { compareVersionMajorAndMinor } from 'src/utils/version/compare-version-minor-and-major';
import { RemoveWorkflowRunsWithoutState } from 'src/database/commands/upgrade-version-command/1-2/1-2-remove-workflow-runs-without-state.command';
const execPromise = promisify(exec);
@ -149,6 +150,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
protected readonly addEnqueuedStatusToWorkflowRunCommand: AddEnqueuedStatusToWorkflowRunCommand,
// 1.2 Commands
protected readonly removeWorkflowRunsWithoutState: RemoveWorkflowRunsWithoutState,
// 1.3 Commands
) {
@ -202,7 +204,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
};
const commands_120: VersionCommands = {
beforeSyncMetadata: [],
beforeSyncMetadata: [this.removeWorkflowRunsWithoutState],
afterSyncMetadata: [],
};

View File

@ -161,27 +161,6 @@ export class WorkflowRunWorkspaceEntity extends BaseWorkspaceEntity {
})
createdBy: ActorMetadata;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.output,
type: FieldMetadataType.RAW_JSON,
label: msg`Output`,
description: msg`Json object to provide output of the workflow run`,
icon: 'IconText',
})
@WorkspaceIsNullable()
output: WorkflowRunOutput | null;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.context,
type: FieldMetadataType.RAW_JSON,
label: msg`Context`,
description: msg`Context`,
icon: 'IconHierarchy2',
})
@WorkspaceIsNullable()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: Record<string, any> | null;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.state,
type: FieldMetadataType.RAW_JSON,
@ -189,8 +168,7 @@ export class WorkflowRunWorkspaceEntity extends BaseWorkspaceEntity {
description: msg`State of the workflow run`,
icon: 'IconHierarchy2',
})
@WorkspaceIsNullable()
state: WorkflowRunState | null;
state: WorkflowRunState;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.position,

View File

@ -103,12 +103,9 @@ export class RunWorkflowJob {
triggerType: workflowVersion.trigger.type,
});
const triggerPayload = workflowRun.context?.trigger ?? {};
await this.workflowRunWorkspaceService.startWorkflowRun({
workflowRunId,
workspaceId,
payload: triggerPayload,
});
await this.throttleExecution(workflowVersion.workflowId);

View File

@ -40,15 +40,14 @@ export class WorkflowRunWorkspaceService {
workflowVersionId,
createdBy,
workflowRunId,
context,
status,
triggerPayload,
}: {
workflowVersionId: string;
createdBy: ActorMetadata;
workflowRunId?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
context: Record<string, any>;
status: WorkflowRunStatus.NOT_STARTED | WorkflowRunStatus.ENQUEUED;
triggerPayload: object;
}) {
const workspaceId =
this.scopedWorkspaceContextFactory.create()?.workspaceId;
@ -108,7 +107,7 @@ export class WorkflowRunWorkspaceService {
workspaceId,
});
const initState = this.getInitState(workflowVersion);
const initState = this.getInitState(workflowVersion, triggerPayload);
const workflowRun = workflowRunRepository.create({
id: workflowRunId ?? v4(),
@ -119,11 +118,6 @@ export class WorkflowRunWorkspaceService {
status,
position,
state: initState,
output: {
...initState,
stepsOutput: {},
},
context,
});
await workflowRunRepository.insert(workflowRun);
@ -135,11 +129,9 @@ export class WorkflowRunWorkspaceService {
async startWorkflowRun({
workflowRunId,
workspaceId,
payload,
}: {
workflowRunId: string;
workspaceId: string;
payload: object;
}) {
const workflowRunToUpdate = await this.getWorkflowRunOrFail({
workflowRunId,
@ -159,29 +151,17 @@ export class WorkflowRunWorkspaceService {
const partialUpdate = {
status: WorkflowRunStatus.RUNNING,
startedAt: new Date().toISOString(),
output: {
...workflowRunToUpdate.output,
stepsOutput: {
trigger: {
result: payload,
},
},
},
state: {
...workflowRunToUpdate.state,
stepInfos: {
...workflowRunToUpdate.state?.stepInfos,
trigger: {
result: {},
...workflowRunToUpdate.state?.stepInfos.trigger,
status: StepStatus.SUCCESS,
result: payload,
},
},
},
context: payload
? {
trigger: payload,
}
: (workflowRunToUpdate.context ?? {}),
};
await this.updateWorkflowRun({ workflowRunId, workspaceId, partialUpdate });
@ -207,10 +187,6 @@ export class WorkflowRunWorkspaceService {
const partialUpdate = {
status,
endedAt: new Date().toISOString(),
output: {
...workflowRunToUpdate.output,
error,
},
state: {
...workflowRunToUpdate.state,
workflowRunError: error,
@ -279,16 +255,6 @@ export class WorkflowRunWorkspaceService {
});
const partialUpdate = {
output: {
flow: workflowRunToUpdate.output?.flow ?? {
trigger: undefined,
steps: [],
},
stepsOutput: {
...(workflowRunToUpdate.output?.stepsOutput ?? {}),
[stepOutput.id]: stepOutput.output,
},
},
state: {
...workflowRunToUpdate.state,
stepInfos: {
@ -301,14 +267,6 @@ export class WorkflowRunWorkspaceService {
},
},
},
...(stepStatus === StepStatus.SUCCESS
? {
context: {
...workflowRunToUpdate.context,
[stepOutput.id]: stepOutput.output.result,
},
}
: {}),
};
await this.updateWorkflowRun({ workflowRunId, workspaceId, partialUpdate });
@ -339,18 +297,11 @@ export class WorkflowRunWorkspaceService {
);
}
const updatedSteps = workflowRunToUpdate.output?.flow?.steps?.map(
const updatedSteps = workflowRunToUpdate.state?.flow?.steps?.map(
(existingStep) => (step.id === existingStep.id ? step : existingStep),
);
const partialUpdate = {
output: {
...(workflowRunToUpdate.output ?? {}),
flow: {
...(workflowRunToUpdate.output?.flow ?? {}),
steps: updatedSteps,
},
},
state: {
...workflowRunToUpdate.state,
flow: {
@ -406,6 +357,7 @@ export class WorkflowRunWorkspaceService {
private getInitState(
workflowVersion: WorkflowVersionWorkspaceEntity,
triggerPayload: object,
): WorkflowRunState | undefined {
if (
!isDefined(workflowVersion.trigger) ||
@ -420,7 +372,7 @@ export class WorkflowRunWorkspaceService {
steps: workflowVersion.steps,
},
stepInfos: {
trigger: { status: StepStatus.NOT_STARTED },
trigger: { status: StepStatus.NOT_STARTED, result: triggerPayload },
...Object.fromEntries(
workflowVersion.steps.map((step) => [
step.id,

View File

@ -75,9 +75,7 @@ export class WorkflowRunnerWorkspaceService {
status: shouldEnqueueWorkflowRun
? WorkflowRunStatus.ENQUEUED
: WorkflowRunStatus.NOT_STARTED,
context: {
trigger: payload,
},
triggerPayload: payload,
});
if (shouldEnqueueWorkflowRun) {