Add throttling on workflow execution (#9263)
We want to avoid infinite loops using workflows. Adding a throttler with a limit of 10 executions / sec by default for each workflow. We were not emitting events on workflow actions so loops could not happen. Since throttler is there we can now and these. Adding an error message so the user knows when it happens. <img width="1284" alt="Capture d’écran 2024-12-27 à 17 05 20" src="https://github.com/user-attachments/assets/dafa837b-5b4c-48be-8207-c90f5c71a236" />
This commit is contained in:
@ -11,4 +11,5 @@ export enum WorkflowRunExceptionCode {
|
||||
WORKFLOW_RUN_NOT_FOUND = 'WORKFLOW_RUN_NOT_FOUND',
|
||||
INVALID_OPERATION = 'INVALID_OPERATION',
|
||||
INVALID_INPUT = 'INVALID_INPUT',
|
||||
WORKFLOW_RUN_LIMIT_REACHED = 'WORKFLOW_RUN_LIMIT_REACHED',
|
||||
}
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
import { Scope } from '@nestjs/common';
|
||||
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator';
|
||||
import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator';
|
||||
import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants';
|
||||
import { ThrottlerService } from 'src/engine/core-modules/throttler/throttler.service';
|
||||
import { WorkflowRunStatus } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
|
||||
import { WorkflowCommonWorkspaceService } from 'src/modules/workflow/common/workspace-services/workflow-common.workspace-service';
|
||||
import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service';
|
||||
import {
|
||||
WorkflowRunException,
|
||||
WorkflowRunExceptionCode,
|
||||
} from 'src/modules/workflow/workflow-runner/exceptions/workflow-run.exception';
|
||||
import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service';
|
||||
|
||||
export type RunWorkflowJobData = {
|
||||
@ -21,6 +27,8 @@ export class RunWorkflowJob {
|
||||
private readonly workflowCommonWorkspaceService: WorkflowCommonWorkspaceService,
|
||||
private readonly workflowExecutorWorkspaceService: WorkflowExecutorWorkspaceService,
|
||||
private readonly workflowRunWorkspaceService: WorkflowRunWorkspaceService,
|
||||
private readonly throttlerService: ThrottlerService,
|
||||
private readonly environmentService: EnvironmentService,
|
||||
) {}
|
||||
|
||||
@Process(RunWorkflowJob.name)
|
||||
@ -36,6 +44,8 @@ export class RunWorkflowJob {
|
||||
workflowVersionId,
|
||||
);
|
||||
|
||||
await this.throttleExecution(workflowVersion.workflowId, workflowRunId);
|
||||
|
||||
const { steps, status } =
|
||||
await this.workflowExecutorWorkspaceService.execute({
|
||||
currentStepIndex: 0,
|
||||
@ -57,4 +67,27 @@ export class RunWorkflowJob {
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private async throttleExecution(workflowId: string, workflowRunId: string) {
|
||||
try {
|
||||
await this.throttlerService.throttle(
|
||||
`${workflowId}-workflow-execution`,
|
||||
this.environmentService.get('WORKFLOW_EXEC_THROTTLE_LIMIT'),
|
||||
this.environmentService.get('WORKFLOW_EXEC_THROTTLE_TTL'),
|
||||
);
|
||||
} catch (error) {
|
||||
await this.workflowRunWorkspaceService.endWorkflowRun(
|
||||
workflowRunId,
|
||||
WorkflowRunStatus.FAILED,
|
||||
{
|
||||
steps: {},
|
||||
error: 'Workflow execution rate limit exceeded',
|
||||
},
|
||||
);
|
||||
throw new WorkflowRunException(
|
||||
'Workflow execution rate limit exceeded',
|
||||
WorkflowRunExceptionCode.WORKFLOW_RUN_LIMIT_REACHED,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { ThrottlerModule } from 'src/engine/core-modules/throttler/throttler.module';
|
||||
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
|
||||
import { WorkflowExecutorModule } from 'src/modules/workflow/workflow-executor/workflow-executor.module';
|
||||
import { RunWorkflowJob } from 'src/modules/workflow/workflow-runner/jobs/run-workflow.job';
|
||||
import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service';
|
||||
import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-run.workspace-service';
|
||||
import { WorkflowRunnerWorkspaceService } from 'src/modules/workflow/workflow-runner/workspace-services/workflow-runner.workspace-service';
|
||||
|
||||
@Module({
|
||||
imports: [WorkflowCommonModule, WorkflowExecutorModule],
|
||||
imports: [WorkflowCommonModule, WorkflowExecutorModule, ThrottlerModule],
|
||||
providers: [
|
||||
WorkflowRunnerWorkspaceService,
|
||||
WorkflowRunWorkspaceService,
|
||||
|
||||
Reference in New Issue
Block a user