diff --git a/packages/server/src/api/controllers/automation.ts b/packages/server/src/api/controllers/automation.ts index 6feba9fb2d..212ef5668f 100644 --- a/packages/server/src/api/controllers/automation.ts +++ b/packages/server/src/api/controllers/automation.ts @@ -1,4 +1,3 @@ -import * as actions from "../../automations/actions" import * as triggers from "../../automations/triggers" import { getAutomationParams, @@ -11,7 +10,7 @@ import { removeDeprecated, } from "../../automations/utils" import { deleteEntityMetadata } from "../../utilities" -import { MetadataTypes } from "../../constants" +import { MetadataTypes, AUTOMATION_SYNC_TIMEOUT } from "../../constants" import { setTestFlag, clearTestFlag } from "../../utilities/redis" import { context, cache, events, db as dbCore } from "@budibase/backend-core" import { automations, features } from "@budibase/pro" @@ -20,7 +19,7 @@ import { Automation, AutomationActionStepId, AutomationResults, - BBContext, + UserCtx, } from "@budibase/types" import { getActionDefinitions as actionDefs } from "../../automations/actions" import sdk from "../../sdk" @@ -72,7 +71,7 @@ function cleanAutomationInputs(automation: Automation) { return automation } -export async function create(ctx: BBContext) { +export async function create(ctx: UserCtx) { const db = context.getAppDB() let automation = ctx.request.body automation.appId = ctx.appId @@ -141,7 +140,7 @@ export async function handleStepEvents( } } -export async function update(ctx: BBContext) { +export async function update(ctx: UserCtx) { const db = context.getAppDB() let automation = ctx.request.body automation.appId = ctx.appId @@ -192,7 +191,7 @@ export async function update(ctx: BBContext) { builderSocket?.emitAutomationUpdate(ctx, automation) } -export async function fetch(ctx: BBContext) { +export async function fetch(ctx: UserCtx) { const db = context.getAppDB() const response = await db.allDocs( getAutomationParams(null, { @@ -202,12 +201,12 @@ export async function fetch(ctx: BBContext) { ctx.body = response.rows.map(row => row.doc) } -export async function find(ctx: BBContext) { +export async function find(ctx: UserCtx) { const db = context.getAppDB() ctx.body = await db.get(ctx.params.id) } -export async function destroy(ctx: BBContext) { +export async function destroy(ctx: UserCtx) { const db = context.getAppDB() const automationId = ctx.params.id const oldAutomation = await db.get(automationId) @@ -221,11 +220,11 @@ export async function destroy(ctx: BBContext) { builderSocket?.emitAutomationDeletion(ctx, automationId) } -export async function logSearch(ctx: BBContext) { +export async function logSearch(ctx: UserCtx) { ctx.body = await automations.logs.logSearch(ctx.request.body) } -export async function clearLogError(ctx: BBContext) { +export async function clearLogError(ctx: UserCtx) { const { automationId, appId } = ctx.request.body await context.doInAppContext(appId, async () => { const db = context.getProdAppDB() @@ -244,15 +243,15 @@ export async function clearLogError(ctx: BBContext) { }) } -export async function getActionList(ctx: BBContext) { +export async function getActionList(ctx: UserCtx) { ctx.body = await getActionDefinitions() } -export async function getTriggerList(ctx: BBContext) { +export async function getTriggerList(ctx: UserCtx) { ctx.body = getTriggerDefinitions() } -export async function getDefinitionList(ctx: BBContext) { +export async function getDefinitionList(ctx: UserCtx) { ctx.body = { trigger: getTriggerDefinitions(), action: await getActionDefinitions(), @@ -265,7 +264,7 @@ export async function getDefinitionList(ctx: BBContext) { * * *********************/ -export async function trigger(ctx: BBContext) { +export async function trigger(ctx: UserCtx) { const db = context.getAppDB() let automation = await db.get(ctx.params.id) @@ -275,7 +274,7 @@ export async function trigger(ctx: BBContext) { automation, { fields: ctx.request.body.fields, - timeout: ctx.request.body.timeout * 1000 || 120000, + timeout: ctx.request.body.timeout * 1000 || AUTOMATION_SYNC_TIMEOUT, }, { getResponses: true } ) @@ -310,7 +309,7 @@ function prepareTestInput(input: any) { return input } -export async function test(ctx: BBContext) { +export async function test(ctx: UserCtx) { const db = context.getAppDB() let automation = await db.get(ctx.params.id) await setTestFlag(automation._id!) diff --git a/packages/server/src/api/controllers/query/index.ts b/packages/server/src/api/controllers/query/index.ts index 1be836b169..8dabe5b3cc 100644 --- a/packages/server/src/api/controllers/query/index.ts +++ b/packages/server/src/api/controllers/query/index.ts @@ -22,7 +22,7 @@ import { import { ValidQueryNameRegex } from "@budibase/shared-core" const Runner = new Thread(ThreadType.QUERY, { - timeoutMs: env.QUERY_THREAD_TIMEOUT || 10000, + timeoutMs: env.QUERY_THREAD_TIMEOUT, }) // simple function to append "readable" to all read queries diff --git a/packages/server/src/automations/steps/bash.ts b/packages/server/src/automations/steps/bash.ts index 61d446f12c..1a13f651ec 100644 --- a/packages/server/src/automations/steps/bash.ts +++ b/packages/server/src/automations/steps/bash.ts @@ -65,7 +65,7 @@ export async function run({ inputs, context }: AutomationStepInput) { success = true try { stdout = execSync(command, { - timeout: environment.QUERY_THREAD_TIMEOUT || 500, + timeout: environment.QUERY_THREAD_TIMEOUT, }).toString() } catch (err: any) { stdout = err.message diff --git a/packages/server/src/automations/steps/executeQuery.ts b/packages/server/src/automations/steps/executeQuery.ts index d3dc6a219c..ea0737c86a 100644 --- a/packages/server/src/automations/steps/executeQuery.ts +++ b/packages/server/src/automations/steps/executeQuery.ts @@ -86,10 +86,7 @@ export async function run({ inputs, appId, emitter }: AutomationStepInput) { }) try { - await Promise.race([ - queryController.executeV2(ctx, { isAutomation: true }), - utils.timeout(env.QUERY_THREAD_TIMEOUT, { reject: true }), - ]) + await queryController.executeV2(ctx, { isAutomation: true }) const { data, ...rest } = ctx.body return { diff --git a/packages/server/src/automations/steps/triggerAutomationRun.ts b/packages/server/src/automations/steps/triggerAutomationRun.ts index cb6126ca01..73c9b3adf1 100644 --- a/packages/server/src/automations/steps/triggerAutomationRun.ts +++ b/packages/server/src/automations/steps/triggerAutomationRun.ts @@ -9,8 +9,9 @@ import { AutomationCustomIOType, } from "@budibase/types" import * as triggers from "../triggers" -import { db as dbCore, context } from "@budibase/backend-core" +import { context } from "@budibase/backend-core" import { features } from "@budibase/pro" +import { AUTOMATION_SYNC_TIMEOUT } from "../../constants" export const definition: AutomationStepSchema = { name: "Trigger an automation", @@ -76,7 +77,7 @@ export async function run({ inputs }: AutomationStepInput) { automation, { fields: { ...fieldParams }, - timeout: inputs.timeout * 1000 || 120000, + timeout: inputs.timeout * 1000 || AUTOMATION_SYNC_TIMEOUT, }, { getResponses: true } ) diff --git a/packages/server/src/automations/tests/triggerAutomationRun.spec.ts b/packages/server/src/automations/tests/triggerAutomationRun.spec.ts index f8cf647e79..83e3c20bbb 100644 --- a/packages/server/src/automations/tests/triggerAutomationRun.spec.ts +++ b/packages/server/src/automations/tests/triggerAutomationRun.spec.ts @@ -3,6 +3,7 @@ jest.spyOn(global.console, "error") import * as setup from "./utilities" import * as automation from "../index" import { serverLogAutomation } from "../../tests/utilities/structures" +import { AUTOMATION_ASYNC_TIMEOUT } from "../../constants" describe("Test triggering an automation from another automation", () => { let config = setup.getConfig() @@ -22,7 +23,10 @@ describe("Test triggering an automation from another automation", () => { let newAutomation = await config.createAutomation(automation) const inputs: any = { - automation: { automationId: newAutomation._id, timeout: 12000 }, + automation: { + automationId: newAutomation._id, + timeout: AUTOMATION_ASYNC_TIMEOUT, + }, } const res = await setup.runStep( setup.actions.TRIGGER_AUTOMATION_RUN.stepId, @@ -33,7 +37,12 @@ describe("Test triggering an automation from another automation", () => { }) it("should fail gracefully if the automation id is incorrect", async () => { - const inputs: any = { automation: { automationId: null, timeout: 12000 } } + const inputs: any = { + automation: { + automationId: null, + timeout: AUTOMATION_ASYNC_TIMEOUT, + }, + } const res = await setup.runStep( setup.actions.TRIGGER_AUTOMATION_RUN.stepId, inputs diff --git a/packages/server/src/constants/automations.ts b/packages/server/src/constants/automations.ts new file mode 100644 index 0000000000..5d83369f87 --- /dev/null +++ b/packages/server/src/constants/automations.ts @@ -0,0 +1,4 @@ +import { Duration } from "@budibase/backend-core" + +export const AUTOMATION_SYNC_TIMEOUT = Duration.fromMinutes(2).toMs() +export const AUTOMATION_ASYNC_TIMEOUT = Duration.fromSeconds(12).toMs() diff --git a/packages/server/src/constants/index.ts b/packages/server/src/constants/index.ts index 49f1d01afb..530cc536ca 100644 --- a/packages/server/src/constants/index.ts +++ b/packages/server/src/constants/index.ts @@ -6,6 +6,8 @@ import { TableSourceType, } from "@budibase/types" +export * from "./automations" + export enum FilterTypes { STRING = "string", FUZZY = "fuzzy", diff --git a/packages/server/src/environment.ts b/packages/server/src/environment.ts index 8e6866d5e4..b3d75070a6 100644 --- a/packages/server/src/environment.ts +++ b/packages/server/src/environment.ts @@ -53,7 +53,9 @@ const environment = { parseIntSafe(process.env.AUTOMATION_MAX_ITERATIONS) || 200, SENDGRID_API_KEY: process.env.SENDGRID_API_KEY, DYNAMO_ENDPOINT: process.env.DYNAMO_ENDPOINT, - QUERY_THREAD_TIMEOUT: parseIntSafe(process.env.QUERY_THREAD_TIMEOUT), + QUERY_THREAD_TIMEOUT: parseIntSafe(process.env.QUERY_THREAD_TIMEOUT) || 10000, + AUTOMATION_THREAD_TIMEOUT: + parseIntSafe(process.env.AUTOMATION_THREAD_TIMEOUT) || 12000, SQL_MAX_ROWS: process.env.SQL_MAX_ROWS, BB_ADMIN_USER_EMAIL: process.env.BB_ADMIN_USER_EMAIL, BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD, diff --git a/packages/server/src/threads/automation.ts b/packages/server/src/threads/automation.ts index a828af5d19..a4938bb138 100644 --- a/packages/server/src/threads/automation.ts +++ b/packages/server/src/threads/automation.ts @@ -303,7 +303,7 @@ class Orchestrator { if (timeout) { setTimeout(() => { timeoutFlag = true - }, timeout || 12000) + }, timeout || env.AUTOMATION_THREAD_TIMEOUT) } stepCount++ @@ -621,7 +621,7 @@ export async function executeInThread(job: Job) { const timeoutPromise = new Promise((resolve, reject) => { setTimeout(() => { reject(new Error("Timeout exceeded")) - }, job.data.event.timeout || 12000) + }, job.data.event.timeout || env.AUTOMATION_THREAD_TIMEOUT) }) return await context.doInAppContext(appId, async () => {