Fix workflow run output empty (#9616)
- catch error on action execution. We will log the error and return it in the step - catch error on workflow run - remove the catch in the action. All actions should simply throw and let the executor do the job <img width="1512" alt="Capture d’écran 2025-01-14 à 17 35 53" src="https://github.com/user-attachments/assets/dcf79567-a309-45f1-a640-c50b7ac4769b" />
This commit is contained in:
@ -10,4 +10,5 @@ export class SendEmailActionException extends CustomException {
|
|||||||
export enum SendEmailActionExceptionCode {
|
export enum SendEmailActionExceptionCode {
|
||||||
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
PROVIDER_NOT_SUPPORTED = 'PROVIDER_NOT_SUPPORTED',
|
||||||
CONNECTED_ACCOUNT_NOT_FOUND = 'CONNECTED_ACCOUNT_NOT_FOUND',
|
CONNECTED_ACCOUNT_NOT_FOUND = 'CONNECTED_ACCOUNT_NOT_FOUND',
|
||||||
|
INVALID_EMAIL = 'INVALID_EMAIL',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,15 +80,15 @@ export class SendEmailWorkflowAction implements WorkflowAction {
|
|||||||
);
|
);
|
||||||
const { email, body, subject } = workflowActionInput;
|
const { email, body, subject } = workflowActionInput;
|
||||||
|
|
||||||
try {
|
|
||||||
const emailSchema = z.string().trim().email('Invalid email');
|
const emailSchema = z.string().trim().email('Invalid email');
|
||||||
|
|
||||||
const result = emailSchema.safeParse(email);
|
const result = emailSchema.safeParse(email);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
this.logger.warn(`Email '${email}' invalid`);
|
throw new SendEmailActionException(
|
||||||
|
`Email '${email}' invalid`,
|
||||||
return { result: { success: false } };
|
SendEmailActionExceptionCode.INVALID_EMAIL,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const window = new JSDOM('').window;
|
const window = new JSDOM('').window;
|
||||||
@ -119,8 +119,5 @@ export class SendEmailWorkflowAction implements WorkflowAction {
|
|||||||
return {
|
return {
|
||||||
result: { success: true } satisfies WorkflowSendEmailStepOutputSchema,
|
result: { success: true } satisfies WorkflowSendEmailStepOutputSchema,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
|
||||||
return { error };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable, Logger } from '@nestjs/common';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
WorkflowRunOutput,
|
WorkflowRunOutput,
|
||||||
@ -6,6 +6,7 @@ import {
|
|||||||
} from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
|
} from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
|
||||||
import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory';
|
import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory';
|
||||||
import { resolveInput } from 'src/modules/workflow/workflow-executor/utils/variable-resolver.util';
|
import { resolveInput } from 'src/modules/workflow/workflow-executor/utils/variable-resolver.util';
|
||||||
|
import { WorkflowActionResult } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action-result.type';
|
||||||
import { WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
import { WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||||
|
|
||||||
const MAX_RETRIES_ON_FAILURE = 3;
|
const MAX_RETRIES_ON_FAILURE = 3;
|
||||||
@ -17,6 +18,7 @@ export type WorkflowExecutorOutput = {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkflowExecutorWorkspaceService {
|
export class WorkflowExecutorWorkspaceService {
|
||||||
|
private readonly logger = new Logger(WorkflowExecutorWorkspaceService.name);
|
||||||
constructor(private readonly workflowActionFactory: WorkflowActionFactory) {}
|
constructor(private readonly workflowActionFactory: WorkflowActionFactory) {}
|
||||||
|
|
||||||
async execute({
|
async execute({
|
||||||
@ -42,7 +44,19 @@ export class WorkflowExecutorWorkspaceService {
|
|||||||
|
|
||||||
const actionPayload = resolveInput(step.settings.input, context);
|
const actionPayload = resolveInput(step.settings.input, context);
|
||||||
|
|
||||||
const result = await workflowAction.execute(actionPayload);
|
let result: WorkflowActionResult;
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = await workflowAction.execute(actionPayload);
|
||||||
|
} catch (error) {
|
||||||
|
result = {
|
||||||
|
error: {
|
||||||
|
errorType: error.name,
|
||||||
|
errorMessage: error.message,
|
||||||
|
stackTrace: error.stack,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const stepOutput = output.steps[step.id];
|
const stepOutput = output.steps[step.id];
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Scope } from '@nestjs/common';
|
import { Logger, Scope } from '@nestjs/common';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||||
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
||||||
@ -23,6 +23,7 @@ export type RunWorkflowJobData = {
|
|||||||
|
|
||||||
@Processor({ queueName: MessageQueue.workflowQueue, scope: Scope.REQUEST })
|
@Processor({ queueName: MessageQueue.workflowQueue, scope: Scope.REQUEST })
|
||||||
export class RunWorkflowJob {
|
export class RunWorkflowJob {
|
||||||
|
private readonly logger = new Logger(RunWorkflowJob.name);
|
||||||
constructor(
|
constructor(
|
||||||
private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService,
|
private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService,
|
||||||
private readonly workflowExecutorWorkspaceService: WorkflowExecutorWorkspaceService,
|
private readonly workflowExecutorWorkspaceService: WorkflowExecutorWorkspaceService,
|
||||||
@ -39,12 +40,13 @@ export class RunWorkflowJob {
|
|||||||
}: RunWorkflowJobData): Promise<void> {
|
}: RunWorkflowJobData): Promise<void> {
|
||||||
await this.workflowRunWorkspaceService.startWorkflowRun(workflowRunId);
|
await this.workflowRunWorkspaceService.startWorkflowRun(workflowRunId);
|
||||||
|
|
||||||
|
try {
|
||||||
const workflowVersion =
|
const workflowVersion =
|
||||||
await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail(
|
await this.workflowCommonWorkspaceService.getWorkflowVersionOrFail(
|
||||||
workflowVersionId,
|
workflowVersionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.throttleExecution(workflowVersion.workflowId, workflowRunId);
|
await this.throttleExecution(workflowVersion.workflowId);
|
||||||
|
|
||||||
const { steps, status } =
|
const { steps, status } =
|
||||||
await this.workflowExecutorWorkspaceService.execute({
|
await this.workflowExecutorWorkspaceService.execute({
|
||||||
@ -66,9 +68,19 @@ export class RunWorkflowJob {
|
|||||||
steps,
|
steps,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
} catch (error) {
|
||||||
|
await this.workflowRunWorkspaceService.endWorkflowRun(
|
||||||
|
workflowRunId,
|
||||||
|
WorkflowRunStatus.FAILED,
|
||||||
|
{
|
||||||
|
steps: {},
|
||||||
|
error: error.message,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async throttleExecution(workflowId: string, workflowRunId: string) {
|
private async throttleExecution(workflowId: string) {
|
||||||
try {
|
try {
|
||||||
await this.throttlerService.throttle(
|
await this.throttlerService.throttle(
|
||||||
`${workflowId}-workflow-execution`,
|
`${workflowId}-workflow-execution`,
|
||||||
@ -76,14 +88,6 @@ export class RunWorkflowJob {
|
|||||||
this.environmentService.get('WORKFLOW_EXEC_THROTTLE_TTL'),
|
this.environmentService.get('WORKFLOW_EXEC_THROTTLE_TTL'),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await this.workflowRunWorkspaceService.endWorkflowRun(
|
|
||||||
workflowRunId,
|
|
||||||
WorkflowRunStatus.FAILED,
|
|
||||||
{
|
|
||||||
steps: {},
|
|
||||||
error: 'Workflow execution rate limit exceeded',
|
|
||||||
},
|
|
||||||
);
|
|
||||||
throw new WorkflowRunException(
|
throw new WorkflowRunException(
|
||||||
'Workflow execution rate limit exceeded',
|
'Workflow execution rate limit exceeded',
|
||||||
WorkflowRunExceptionCode.WORKFLOW_RUN_LIMIT_REACHED,
|
WorkflowRunExceptionCode.WORKFLOW_RUN_LIMIT_REACHED,
|
||||||
|
|||||||
Reference in New Issue
Block a user