From 00fda6af4127263a04a1558da9ef5648d4f1fb68 Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 18 Jan 2024 16:38:34 +0000 Subject: [PATCH 01/32] update emitter to account for a new chaining property --- .../server/src/events/AutomationEmitter.ts | 37 ++++++++++++------- packages/types/src/documents/app/app.ts | 6 +++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/server/src/events/AutomationEmitter.ts b/packages/server/src/events/AutomationEmitter.ts index 9d476d5088..3297fc7263 100644 --- a/packages/server/src/events/AutomationEmitter.ts +++ b/packages/server/src/events/AutomationEmitter.ts @@ -1,18 +1,9 @@ import { rowEmission, tableEmission } from "./utils" import mainEmitter from "./index" import env from "../environment" -import { Table, Row } from "@budibase/types" +import { Table, Row, DocumentType, App } from "@budibase/types" +import { context } from "@budibase/backend-core" -// max number of automations that can chain on top of each other -// TODO: in future make this configurable at the automation level -const MAX_AUTOMATION_CHAIN = env.SELF_HOSTED ? 5 : 0 - -/** - * Special emitter which takes the count of automation runs which have occurred and blocks an - * automation from running if it has reached the maximum number of chained automations runs. - * This essentially "fakes" the normal emitter to add some functionality in-between to stop automations - * from getting stuck endlessly chaining. - */ class AutomationEmitter { chainCount: number metadata: { automationChainCount: number } @@ -24,7 +15,23 @@ class AutomationEmitter { } } - emitRow(eventName: string, appId: string, row: Row, table?: Table) { + async getMaxAutomationChain() { + const db = context.getAppDB() + const appMetadata = await db.get(DocumentType.APP_METADATA) + let chainAutomations = appMetadata?.automations?.chainAutomations + + if (chainAutomations === true) { + return 5 + } else if (chainAutomations === undefined && env.SELF_HOSTED) { + return 5 + } else { + return 0 + } + } + + async emitRow(eventName: string, appId: string, row: Row, table?: Table) { + let MAX_AUTOMATION_CHAIN = await this.getMaxAutomationChain() + // don't emit even if we've reached max automation chain if (this.chainCount >= MAX_AUTOMATION_CHAIN) { return @@ -39,9 +46,11 @@ class AutomationEmitter { }) } - emitTable(eventName: string, appId: string, table?: Table) { + async emitTable(eventName: string, appId: string, table?: Table) { + let MAX_AUTOMATION_CHAIN = await this.getMaxAutomationChain() + // don't emit even if we've reached max automation chain - if (this.chainCount > MAX_AUTOMATION_CHAIN) { + if (this.chainCount >= MAX_AUTOMATION_CHAIN) { return } diff --git a/packages/types/src/documents/app/app.ts b/packages/types/src/documents/app/app.ts index 5bbdd86515..e1174d4fe4 100644 --- a/packages/types/src/documents/app/app.ts +++ b/packages/types/src/documents/app/app.ts @@ -23,6 +23,7 @@ export interface App extends Document { automationErrors?: AppMetadataErrors icon?: AppIcon features?: AppFeatures + automations: AutomationSettings } export interface AppInstance { @@ -67,4 +68,9 @@ export interface AppIcon { export interface AppFeatures { componentValidation?: boolean disableUserMetadata?: boolean + enableAutomationChaining?: boolean +} + +export interface AutomationSettings { + chainAutomations?: boolean } From b05484bb49c6f941ec57eff3525b5bebe049c24c Mon Sep 17 00:00:00 2001 From: Peter Clement Date: Thu, 18 Jan 2024 16:38:51 +0000 Subject: [PATCH 02/32] frontend toggle for new automation chaining and update settings ux --- .../src/builderStore/store/frontend.js | 1 + .../components/start/ChooseIconModal.svelte | 1 + .../settings/automation-history/index.svelte | 46 +++++++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index b05b127b1c..af48afb1bc 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -65,6 +65,7 @@ const INITIAL_FRONTEND_STATE = { features: { componentValidation: false, disableUserMetadata: false, + enableAutomationChaining: false, }, errors: [], hasAppPackage: false, diff --git a/packages/builder/src/components/start/ChooseIconModal.svelte b/packages/builder/src/components/start/ChooseIconModal.svelte index 1ffaa35e34..1f26cb93ec 100644 --- a/packages/builder/src/components/start/ChooseIconModal.svelte +++ b/packages/builder/src/components/start/ChooseIconModal.svelte @@ -49,6 +49,7 @@ return } try { + console.log(app.instance._id) await apps.update(app.instance._id, { icon: { name, color }, }) diff --git a/packages/builder/src/pages/builder/app/[application]/settings/automation-history/index.svelte b/packages/builder/src/pages/builder/app/[application]/settings/automation-history/index.svelte index 373a47aa2e..4ff3409b09 100644 --- a/packages/builder/src/pages/builder/app/[application]/settings/automation-history/index.svelte +++ b/packages/builder/src/pages/builder/app/[application]/settings/automation-history/index.svelte @@ -8,6 +8,8 @@ Body, Heading, Divider, + Toggle, + notifications, } from "@budibase/bbui" import DateTimeRenderer from "components/common/renderers/DateTimeRenderer.svelte" import StatusRenderer from "./_components/StatusRenderer.svelte" @@ -16,7 +18,7 @@ import { createPaginationStore } from "helpers/pagination" import { getContext, onDestroy, onMount } from "svelte" import dayjs from "dayjs" - import { auth, licensing, admin } from "stores/portal" + import { auth, licensing, admin, apps } from "stores/portal" import { Constants } from "@budibase/frontend-core" import Portal from "svelte-portal" @@ -35,9 +37,13 @@ let timeRange = null let loaded = false + $: app = $apps.find(app => app.devId === $store.appId) $: licensePlan = $auth.user?.license?.plan $: page = $pageInfo.page $: fetchLogs(automationId, status, page, timeRange) + $: isCloud = $admin.cloud + + $: chainAutomations = app?.automations?.chainAutomations ?? !isCloud const timeOptions = [ { value: "90-d", label: "Past 90 days" }, @@ -124,6 +130,18 @@ sidePanel.open() } + async function save({ detail }) { + try { + await apps.update($store.appId, { + automations: { + chainAutomations: detail, + }, + }) + } catch (error) { + notifications.error("Error updating automation chaining setting") + } + } + onMount(async () => { await automationStore.actions.fetch() const params = new URLSearchParams(window.location.search) @@ -150,11 +168,30 @@ - Automation History - View the automations your app has executed + Automations + See your automation history and edit advanced settings + + Chain automations + Allow automations to trigger from other automations +
+ { + save(e) + }} + value={chainAutomations} + /> +
+
+ + + + History + Free plan stores up to 1 day of automation history +