Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update workflow version struct #6716

Merged
merged 3 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ export const WORKFLOW_VERSION_STANDARD_FIELD_IDS = {
workflow: '20202020-afa3-46c3-91b0-0631ca6aa1c8',
trigger: '20202020-4eae-43e7-86e0-212b41a30b48',
runs: '20202020-1d08-46df-901a-85045f18099a',
steps: '20202020-5988-4a64-b94a-1f9b7b989039',
};

export const WORKSPACE_MEMBER_STANDARD_FIELD_IDS = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { WorkflowStep } from 'src/modules/workflow/common/types/workflow-step.type';
import { WorkflowTrigger } from 'src/modules/workflow/common/types/workflow-trigger.type';

@WorkspaceEntity({
Expand Down Expand Up @@ -51,11 +52,19 @@ export class WorkflowVersionWorkspaceEntity extends BaseWorkspaceEntity {
type: FieldMetadataType.RAW_JSON,
label: 'Version trigger',
description: 'Json object to provide trigger',
icon: 'IconPlayerPlay',
})
@WorkspaceIsNullable()
trigger: WorkflowTrigger | null;

@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.steps,
type: FieldMetadataType.RAW_JSON,
label: 'Version steps',
description: 'Json object to provide steps',
})
@WorkspaceIsNullable()
steps: WorkflowStep[] | null;

// Relations
@WorkspaceRelation({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.workflow,
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type WorkflowBaseSettingsType = {
type BaseWorkflowSettings = {
errorHandlingOptions: {
retryOnFailure: {
value: boolean;
Expand All @@ -9,6 +9,6 @@ type WorkflowBaseSettingsType = {
};
};

export type WorkflowCodeSettingsType = WorkflowBaseSettingsType & {
export type WorkflowCodeSettings = BaseWorkflowSettings & {
serverlessFunctionId: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { WorkflowCodeSettings } from 'src/modules/workflow/common/types/workflow-settings.type';

export enum WorkflowStepType {
CODE_ACTION = 'CODE_ACTION',
}

type BaseWorkflowStep = {
id: string;
name: string;
valid: boolean;
};
Comment on lines +7 to +11
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Add a type field to BaseWorkflowStep for better type safety when handling different step types


export type WorkflowCodeStep = BaseWorkflowStep & {
type: WorkflowStepType.CODE_ACTION;
settings: WorkflowCodeSettings;
};

export type WorkflowStep = WorkflowCodeStep;
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import { WorkflowAction } from 'src/modules/workflow/common/types/workflow-action.type';

export enum WorkflowTriggerType {
DATABASE_EVENT = 'DATABASE_EVENT',
}

type BaseTrigger = {
name: string;
type: WorkflowTriggerType;
input?: object;
nextAction?: WorkflowAction;
};

export type WorkflowDatabaseEventTrigger = BaseTrigger & {
type: WorkflowTriggerType.DATABASE_EVENT;
settings: {
eventName: string;
triggerName: string;
};
};

Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Module } from '@nestjs/common';

import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
import { WorkflowActionExecutorModule } from 'src/modules/workflow/workflow-action-executor/workflow-action-executor.module';
import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workflow-executor.workspace-service';
import { WorkflowStepExecutorModule } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.module';

@Module({
imports: [WorkflowCommonModule, WorkflowActionExecutorModule],
imports: [WorkflowCommonModule, WorkflowStepExecutorModule],
providers: [WorkflowExecutorWorkspaceService],
exports: [WorkflowExecutorWorkspaceService],
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Injectable } from '@nestjs/common';

import { WorkflowAction } from 'src/modules/workflow/common/types/workflow-action.type';
import { WorkflowActionExecutorFactory } from 'src/modules/workflow/workflow-action-executor/workflow-action-executor.factory';
import { WorkflowStep } from 'src/modules/workflow/common/types/workflow-step.type';
import {
WorkflowExecutorException,
WorkflowExecutorExceptionCode,
} from 'src/modules/workflow/workflow-executor/workflow-executor.exception';
import { WorkflowStepExecutorFactory } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.factory';

const MAX_RETRIES_ON_FAILURE = 3;

Expand All @@ -17,36 +17,41 @@ export type WorkflowExecutionOutput = {
@Injectable()
export class WorkflowExecutorWorkspaceService {
constructor(
private readonly workflowActionExecutorFactory: WorkflowActionExecutorFactory,
private readonly workflowStepExecutorFactory: WorkflowStepExecutorFactory,
) {}

async execute({
action,
currentStepIndex,
steps,
payload,
attemptCount = 1,
}: {
action?: WorkflowAction;
currentStepIndex: number;
steps: WorkflowStep[];
payload?: object;
attemptCount?: number;
}): Promise<WorkflowExecutionOutput> {
if (!action) {
if (currentStepIndex >= steps.length) {
return {
data: payload,
};
}

const workflowActionExecutor = this.workflowActionExecutorFactory.get(
action.type,
const step = steps[currentStepIndex];

const workflowStepExecutor = this.workflowStepExecutorFactory.get(
step.type,
);

const result = await workflowActionExecutor.execute({
action,
const result = await workflowStepExecutor.execute({
step,
payload,
});

if (result.data) {
return await this.execute({
action: action.nextAction,
currentStepIndex: currentStepIndex + 1,
steps,
payload: result.data,
});
}
Expand All @@ -58,19 +63,21 @@ export class WorkflowExecutorWorkspaceService {
);
}

if (action.settings.errorHandlingOptions.continueOnFailure.value) {
if (step.settings.errorHandlingOptions.continueOnFailure.value) {
return await this.execute({
action: action.nextAction,
currentStepIndex: currentStepIndex + 1,
steps,
payload,
});
}

if (
action.settings.errorHandlingOptions.retryOnFailure.value &&
step.settings.errorHandlingOptions.retryOnFailure.value &&
attemptCount < MAX_RETRIES_ON_FAILURE
) {
return await this.execute({
action,
currentStepIndex,
steps,
payload,
attemptCount: attemptCount + 1,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ export class RunWorkflowJob {

try {
await this.workflowExecutorWorkspaceService.execute({
action: workflowVersion.trigger.nextAction,
currentStepIndex: 0,
steps: workflowVersion.steps || [],
payload,
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { CustomException } from 'src/utils/custom-exception';

export class WorkflowStepExecutorException extends CustomException {
code: WorkflowStepExecutorExceptionCode;
constructor(message: string, code: WorkflowStepExecutorExceptionCode) {
super(message, code);
}
}

export enum WorkflowStepExecutorExceptionCode {
SCOPED_WORKSPACE_NOT_FOUND = 'SCOPED_WORKSPACE_NOT_FOUND',
INVALID_STEP_TYPE = 'INVALID_STEP_TYPE',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Injectable } from '@nestjs/common';

import { WorkflowStepType } from 'src/modules/workflow/common/types/workflow-step.type';
import {
WorkflowStepExecutorException,
WorkflowStepExecutorExceptionCode,
} from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.exception';
import { WorkflowStepExecutor } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.interface';
import { CodeActionExecutor } from 'src/modules/workflow/workflow-step-executor/workflow-step-executors/code-action-executor';

@Injectable()
export class WorkflowStepExecutorFactory {
constructor(private readonly codeActionExecutor: CodeActionExecutor) {}

get(stepType: WorkflowStepType): WorkflowStepExecutor {
switch (stepType) {
case WorkflowStepType.CODE_ACTION:
return this.codeActionExecutor;
default:
throw new WorkflowStepExecutorException(
`Workflow step executor not found for step type '${stepType}'`,
WorkflowStepExecutorExceptionCode.INVALID_STEP_TYPE,
);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { WorkflowAction } from 'src/modules/workflow/common/types/workflow-action.type';
import { WorkflowResult } from 'src/modules/workflow/common/types/workflow-result.type';
import { WorkflowStep } from 'src/modules/workflow/common/types/workflow-step.type';

export interface WorkflowActionExecutor {
export interface WorkflowStepExecutor {
execute({
action,
step,
payload,
}: {
action: WorkflowAction;
step: WorkflowStep;
payload?: object;
}): Promise<WorkflowResult>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Module } from '@nestjs/common';

import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
import { WorkflowStepExecutorFactory } from 'src/modules/workflow/workflow-step-executor/workflow-step-executor.factory';
import { CodeActionExecutor } from 'src/modules/workflow/workflow-step-executor/workflow-step-executors/code-action-executor';

@Module({
imports: [ServerlessFunctionModule],
providers: [
WorkflowStepExecutorFactory,
CodeActionExecutor,
ScopedWorkspaceContextFactory,
],
exports: [WorkflowStepExecutorFactory],
})
export class WorkflowStepExecutorModule {}
Loading
Loading