Skip to content

Commit

Permalink
Resolve variables
Browse files Browse the repository at this point in the history
  • Loading branch information
thomtrp committed Oct 15, 2024
1 parent 1330a1c commit 48367c5
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ export class WorkflowExecutorException extends CustomException {

export enum WorkflowExecutorExceptionCode {
WORKFLOW_FAILED = 'WORKFLOW_FAILED',
VARIABLE_EVALUATION_FAILED = 'VARIABLE_EVALUATION_FAILED',
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { isNil, isString } from '@nestjs/common/utils/shared.utils';

import Handlebars from 'handlebars';

import {
WorkflowExecutorException,
WorkflowExecutorExceptionCode,
} from 'src/modules/workflow/workflow-executor/exceptions/workflow-executor.exception';

const VARIABLE_PATTERN = RegExp('\\{\\{(.*?)\\}\\}', 'g');

export const resolve = (
unresolvedInput: any,
context: Record<string, object>,
) => {
if (isNil(unresolvedInput)) {
return unresolvedInput;
}

if (isString(unresolvedInput)) {
return resolveString(unresolvedInput, context);
}

const resolvedInput = unresolvedInput;

if (Array.isArray(unresolvedInput)) {
for (let i = 0; i < unresolvedInput.length; ++i) {
resolvedInput[i] = resolve(unresolvedInput[i], context);
}
} else if (typeof unresolvedInput === 'object') {
const entries = Object.entries(unresolvedInput);

for (const [key, value] of entries) {
resolvedInput[key] = resolve(value, context);
}
}

return resolvedInput;
};

const resolveString = (
input: string,
context: Record<string, object>,
): string => {
const matchedTokens = input.match(VARIABLE_PATTERN);

if (!matchedTokens || matchedTokens.length === 0) {
return input;
}

if (matchedTokens.length === 1 && matchedTokens[0] === input) {
return evalFromContext(input, context);
}

return input.replace(VARIABLE_PATTERN, (matchedToken, _) => {
const processedToken = evalFromContext(matchedToken, context);

return processedToken;
});
};

const evalFromContext = (
input: string,
context: Record<string, object>,
): string => {
try {
const inferedInput = Handlebars.compile(input)(context);

return inferedInput ?? '';
} catch (exception) {
throw new WorkflowExecutorException(
`Failed to evaluate variable ${input}: ${exception}`,
WorkflowExecutorExceptionCode.VARIABLE_EVALUATION_FAILED,
);
}
};
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Module } from '@nestjs/common';

import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service';
import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory';
import { CodeWorkflowAction } from 'src/modules/serverless/workflow-actions/code.workflow-action';
import { SendEmailWorkflowAction } from 'src/modules/mail-sender/workflow-actions/send-email.workflow-action';
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 { SendEmailWorkflowAction } from 'src/modules/mail-sender/workflow-actions/send-email.workflow-action';
import { MessagingGmailDriverModule } from 'src/modules/messaging/message-import-manager/drivers/gmail/messaging-gmail-driver.module';
import { CodeWorkflowAction } from 'src/modules/serverless/workflow-actions/code.workflow-action';
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory';
import { WorkflowExecutorWorkspaceService } from 'src/modules/workflow/workflow-executor/workspace-services/workflow-executor.workspace-service';

@Module({
imports: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { WorkflowActionFactory } from 'src/modules/workflow/workflow-executor/factories/workflow-action.factory';
import { WorkflowStep } from 'src/modules/workflow/workflow-executor/types/workflow-action.type';
import { resolve } from 'src/modules/workflow/workflow-executor/utils/variable-resolver.util';

const MAX_RETRIES_ON_FAILURE = 3;

Expand All @@ -28,7 +29,7 @@ export class WorkflowExecutorWorkspaceService {
currentStepIndex: number;
steps: WorkflowStep[];
output: WorkflowExecutorOutput;
context?: Record<string, any>;
context: Record<string, any>;
attemptCount?: number;
}): Promise<WorkflowExecutorOutput> {
if (currentStepIndex >= steps.length) {
Expand All @@ -39,12 +40,20 @@ export class WorkflowExecutorWorkspaceService {

const workflowAction = this.workflowActionFactory.get(step.type);

const inferedStepInput = await resolve(step.settings.input, context);

const result = await workflowAction.execute({
step,
step: {
...step,
settings: {
...step.settings,
input: inferedStepInput,
},
},
context,
});

const stepOutput = output.steps[step.name];
const stepOutput = output.steps[step.id];

const error =
result.error?.errorMessage ??
Expand All @@ -68,7 +77,7 @@ export class WorkflowExecutorWorkspaceService {
...output,
steps: {
...output.steps,
[step.name]: updatedStepOutput,
[step.id]: updatedStepOutput,
},
};

Expand All @@ -78,7 +87,7 @@ export class WorkflowExecutorWorkspaceService {
steps,
context: {
...context,
[step.name]: result.result,
[step.id]: result.result,
},
output: updatedOutput,
});
Expand Down

0 comments on commit 48367c5

Please sign in to comment.