From ba401ec972c5eae653a25df2b77adc15ebc653e3 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Wed, 15 Oct 2025 11:42:19 -0700 Subject: [PATCH 1/4] improvement(functions): increase function block timeout to 3 min --- apps/sim/app/api/function/execute/route.ts | 4 ++-- apps/sim/executor/handlers/function/function-handler.ts | 2 +- apps/sim/tools/function/execute.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/sim/app/api/function/execute/route.ts b/apps/sim/app/api/function/execute/route.ts index 31a5340d463..129cf13ebb6 100644 --- a/apps/sim/app/api/function/execute/route.ts +++ b/apps/sim/app/api/function/execute/route.ts @@ -8,7 +8,7 @@ import { validateProxyUrl } from '@/lib/security/input-validation' import { generateRequestId } from '@/lib/utils' export const dynamic = 'force-dynamic' export const runtime = 'nodejs' -export const maxDuration = 60 +export const maxDuration = 300 const logger = createLogger('FunctionExecuteAPI') @@ -652,7 +652,7 @@ export async function POST(req: NextRequest) { const { code, params = {}, - timeout = 5000, + timeout = 180000, language = DEFAULT_CODE_LANGUAGE, useLocalVM = false, envVars = {}, diff --git a/apps/sim/executor/handlers/function/function-handler.ts b/apps/sim/executor/handlers/function/function-handler.ts index dac9b958cfb..a06f626ff9c 100644 --- a/apps/sim/executor/handlers/function/function-handler.ts +++ b/apps/sim/executor/handlers/function/function-handler.ts @@ -61,7 +61,7 @@ export class FunctionBlockHandler implements BlockHandler { code: codeContent, language: inputs.language || DEFAULT_CODE_LANGUAGE, useLocalVM: !inputs.remoteExecution, - timeout: inputs.timeout || 5000, + timeout: inputs.timeout || 180000, envVars: context.environmentVariables || {}, workflowVariables: context.workflowVariables || {}, blockData: blockData, // Pass block data for variable resolution diff --git a/apps/sim/tools/function/execute.ts b/apps/sim/tools/function/execute.ts index e8c9ca6a32f..28590e7eaf7 100644 --- a/apps/sim/tools/function/execute.ts +++ b/apps/sim/tools/function/execute.ts @@ -2,7 +2,7 @@ import { DEFAULT_CODE_LANGUAGE } from '@/lib/execution/languages' import type { CodeExecutionInput, CodeExecutionOutput } from '@/tools/function/types' import type { ToolConfig } from '@/tools/types' -const DEFAULT_TIMEOUT = 10000 // 10 seconds +const DEFAULT_TIMEOUT = 180000 // 3 minutes export const functionExecuteTool: ToolConfig = { id: 'function_execute', From 366ea290e096ba7a885cee317b84b19c73032544 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Wed, 15 Oct 2025 11:46:49 -0700 Subject: [PATCH 2/4] fix tests --- apps/sim/executor/handlers/function/function-handler.test.ts | 2 +- apps/sim/tools/function/execute.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sim/executor/handlers/function/function-handler.test.ts b/apps/sim/executor/handlers/function/function-handler.test.ts index f1054743a2a..f93968da3fb 100644 --- a/apps/sim/executor/handlers/function/function-handler.test.ts +++ b/apps/sim/executor/handlers/function/function-handler.test.ts @@ -138,7 +138,7 @@ describe('FunctionBlockHandler', () => { code: inputs.code, language: 'javascript', useLocalVM: true, - timeout: 5000, // Default timeout + timeout: 180000, // Default timeout (3 minutes) envVars: {}, workflowVariables: {}, blockData: {}, diff --git a/apps/sim/tools/function/execute.test.ts b/apps/sim/tools/function/execute.test.ts index ff9a45e4899..9ccc45d7611 100644 --- a/apps/sim/tools/function/execute.test.ts +++ b/apps/sim/tools/function/execute.test.ts @@ -95,7 +95,7 @@ describe('Function Execute Tool', () => { expect(body).toEqual({ code: 'return 42', - timeout: 10000, + timeout: 180000, envVars: {}, workflowVariables: {}, blockData: {}, From def94702a1874757b9f61c628f5ae44a73a0f325 Mon Sep 17 00:00:00 2001 From: Vikhyath Mondreti Date: Wed, 15 Oct 2025 11:50:05 -0700 Subject: [PATCH 3/4] use shared constant --- apps/sim/app/api/function/execute/route.ts | 8 ++++++-- .../handlers/function/function-handler.test.ts | 9 +++++---- .../sim/executor/handlers/function/function-handler.ts | 3 ++- apps/sim/lib/execution/constants.ts | 10 ++++++++++ apps/sim/tools/function/execute.test.ts | 3 ++- apps/sim/tools/function/execute.ts | 7 +++---- 6 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 apps/sim/lib/execution/constants.ts diff --git a/apps/sim/app/api/function/execute/route.ts b/apps/sim/app/api/function/execute/route.ts index 129cf13ebb6..e1dd7573f61 100644 --- a/apps/sim/app/api/function/execute/route.ts +++ b/apps/sim/app/api/function/execute/route.ts @@ -1,6 +1,7 @@ import { createContext, Script } from 'vm' import { type NextRequest, NextResponse } from 'next/server' import { env, isTruthy } from '@/lib/env' +import { MAX_EXECUTION_DURATION } from '@/lib/execution/constants' import { executeInE2B } from '@/lib/execution/e2b' import { CodeLanguage, DEFAULT_CODE_LANGUAGE, isValidCodeLanguage } from '@/lib/execution/languages' import { createLogger } from '@/lib/logs/console/logger' @@ -8,7 +9,7 @@ import { validateProxyUrl } from '@/lib/security/input-validation' import { generateRequestId } from '@/lib/utils' export const dynamic = 'force-dynamic' export const runtime = 'nodejs' -export const maxDuration = 300 +export const maxDuration = MAX_EXECUTION_DURATION const logger = createLogger('FunctionExecuteAPI') @@ -649,10 +650,13 @@ export async function POST(req: NextRequest) { try { const body = await req.json() + // Import timeout constant dynamically to avoid circular deps + const { DEFAULT_EXECUTION_TIMEOUT_MS } = await import('@/lib/execution/constants') + const { code, params = {}, - timeout = 180000, + timeout = DEFAULT_EXECUTION_TIMEOUT_MS, language = DEFAULT_CODE_LANGUAGE, useLocalVM = false, envVars = {}, diff --git a/apps/sim/executor/handlers/function/function-handler.test.ts b/apps/sim/executor/handlers/function/function-handler.test.ts index f93968da3fb..ad48e088051 100644 --- a/apps/sim/executor/handlers/function/function-handler.test.ts +++ b/apps/sim/executor/handlers/function/function-handler.test.ts @@ -1,4 +1,5 @@ import { beforeEach, describe, expect, it, type Mock, vi } from 'vitest' +import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/execution/constants' import { BlockType } from '@/executor/consts' import { FunctionBlockHandler } from '@/executor/handlers/function/function-handler' import type { ExecutionContext } from '@/executor/types' @@ -82,7 +83,7 @@ describe('FunctionBlockHandler', () => { workflowVariables: {}, blockData: {}, blockNameMapping: {}, - _context: { workflowId: mockContext.workflowId }, + _context: { workflowId: mockContext.workflowId, workspaceId: mockContext.workspaceId }, } const expectedOutput: any = { result: 'Success' } @@ -116,7 +117,7 @@ describe('FunctionBlockHandler', () => { workflowVariables: {}, blockData: {}, blockNameMapping: {}, - _context: { workflowId: mockContext.workflowId }, + _context: { workflowId: mockContext.workflowId, workspaceId: mockContext.workspaceId }, } const expectedOutput: any = { result: 'Success' } @@ -138,12 +139,12 @@ describe('FunctionBlockHandler', () => { code: inputs.code, language: 'javascript', useLocalVM: true, - timeout: 180000, // Default timeout (3 minutes) + timeout: DEFAULT_EXECUTION_TIMEOUT_MS, envVars: {}, workflowVariables: {}, blockData: {}, blockNameMapping: {}, - _context: { workflowId: mockContext.workflowId }, + _context: { workflowId: mockContext.workflowId, workspaceId: mockContext.workspaceId }, } await handler.execute(mockBlock, inputs, mockContext) diff --git a/apps/sim/executor/handlers/function/function-handler.ts b/apps/sim/executor/handlers/function/function-handler.ts index a06f626ff9c..9d71759258b 100644 --- a/apps/sim/executor/handlers/function/function-handler.ts +++ b/apps/sim/executor/handlers/function/function-handler.ts @@ -1,3 +1,4 @@ +import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/execution/constants' import { DEFAULT_CODE_LANGUAGE } from '@/lib/execution/languages' import { createLogger } from '@/lib/logs/console/logger' import { BlockType } from '@/executor/consts' @@ -61,7 +62,7 @@ export class FunctionBlockHandler implements BlockHandler { code: codeContent, language: inputs.language || DEFAULT_CODE_LANGUAGE, useLocalVM: !inputs.remoteExecution, - timeout: inputs.timeout || 180000, + timeout: inputs.timeout || DEFAULT_EXECUTION_TIMEOUT_MS, envVars: context.environmentVariables || {}, workflowVariables: context.workflowVariables || {}, blockData: blockData, // Pass block data for variable resolution diff --git a/apps/sim/lib/execution/constants.ts b/apps/sim/lib/execution/constants.ts new file mode 100644 index 00000000000..4fcdab36505 --- /dev/null +++ b/apps/sim/lib/execution/constants.ts @@ -0,0 +1,10 @@ +/** + * Execution timeout constants + * + * These constants define the timeout values for code execution. + * - DEFAULT_EXECUTION_TIMEOUT_MS: The default timeout for executing user code (3 minutes) + * - MAX_EXECUTION_DURATION: The maximum duration for the API route (adds 30s buffer for overhead) + */ + +export const DEFAULT_EXECUTION_TIMEOUT_MS = 180000 // 3 minutes (180 seconds) +export const MAX_EXECUTION_DURATION = 210 // 3.5 minutes (210 seconds) - includes buffer for sandbox creation diff --git a/apps/sim/tools/function/execute.test.ts b/apps/sim/tools/function/execute.test.ts index 9ccc45d7611..8b778a20682 100644 --- a/apps/sim/tools/function/execute.test.ts +++ b/apps/sim/tools/function/execute.test.ts @@ -7,6 +7,7 @@ * which runs JavaScript code in a secure sandbox. */ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/execution/constants' import { ToolTester } from '@/tools/__test-utils__/test-tools' import { functionExecuteTool } from '@/tools/function/execute' @@ -95,7 +96,7 @@ describe('Function Execute Tool', () => { expect(body).toEqual({ code: 'return 42', - timeout: 180000, + timeout: DEFAULT_EXECUTION_TIMEOUT_MS, envVars: {}, workflowVariables: {}, blockData: {}, diff --git a/apps/sim/tools/function/execute.ts b/apps/sim/tools/function/execute.ts index 28590e7eaf7..c64291e4115 100644 --- a/apps/sim/tools/function/execute.ts +++ b/apps/sim/tools/function/execute.ts @@ -1,9 +1,8 @@ +import { DEFAULT_EXECUTION_TIMEOUT_MS } from '@/lib/execution/constants' import { DEFAULT_CODE_LANGUAGE } from '@/lib/execution/languages' import type { CodeExecutionInput, CodeExecutionOutput } from '@/tools/function/types' import type { ToolConfig } from '@/tools/types' -const DEFAULT_TIMEOUT = 180000 // 3 minutes - export const functionExecuteTool: ToolConfig = { id: 'function_execute', name: 'Function Execute', @@ -38,7 +37,7 @@ export const functionExecuteTool: ToolConfig Date: Wed, 15 Oct 2025 11:50:56 -0700 Subject: [PATCH 4/4] remove comment --- apps/sim/app/api/function/execute/route.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/sim/app/api/function/execute/route.ts b/apps/sim/app/api/function/execute/route.ts index e1dd7573f61..d1dc9190aab 100644 --- a/apps/sim/app/api/function/execute/route.ts +++ b/apps/sim/app/api/function/execute/route.ts @@ -650,7 +650,6 @@ export async function POST(req: NextRequest) { try { const body = await req.json() - // Import timeout constant dynamically to avoid circular deps const { DEFAULT_EXECUTION_TIMEOUT_MS } = await import('@/lib/execution/constants') const {