@budibase/server 1.1.32-alpha.4 → 1.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/builder/assets/index.133db51f.js +978 -0
- package/builder/assets/{index.bdcef434.css → index.192adf4c.css} +2 -2
- package/builder/assets/{vendor.6bcafa60.js → vendor.162098da.js} +1 -1
- package/builder/index.html +3 -3
- package/coverage/clover.xml +696 -381
- package/coverage/coverage-final.json +16 -13
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +1 -1
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +1 -1
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
- package/coverage/lcov-report/api/controllers/query/index.html +1 -1
- package/coverage/lcov-report/api/controllers/query/validation.js.html +4 -4
- package/coverage/lcov-report/api/controllers/role.js.html +1 -1
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/index.html +18 -18
- package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +49 -94
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/screen.js.html +1 -1
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +15 -15
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +1 -1
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +1 -1
- package/coverage/lcov-report/api/routes/utils/index.html +1 -1
- package/coverage/lcov-report/api/routes/utils/validators.js.html +2 -2
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +17 -17
- package/coverage/lcov-report/automations/index.html +1 -1
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +2 -5
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
- package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +18 -18
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +14 -5
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
- package/coverage/lcov-report/db/index.html +19 -19
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
- package/coverage/lcov-report/db/newid.js.html +1 -1
- package/coverage/lcov-report/db/utils.js.html +13 -61
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +1 -1
- package/coverage/lcov-report/index.html +72 -57
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
- package/coverage/lcov-report/middleware/builder.js.html +1 -1
- package/coverage/lcov-report/middleware/currentapp.js.html +1 -1
- package/coverage/lcov-report/middleware/index.html +21 -21
- package/coverage/lcov-report/middleware/joi-validator.js.html +43 -43
- package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
- package/coverage/lcov-report/middleware/resourceId.js.html +1 -1
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/threads/automation.js.html +1114 -0
- package/coverage/lcov-report/threads/index.html +146 -0
- package/coverage/lcov-report/threads/query.js.html +916 -0
- package/coverage/lcov-report/threads/utils.js.html +319 -0
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +14 -68
- package/coverage/lcov-report/utilities/index.html +19 -19
- package/coverage/lcov-report/utilities/index.js.html +1 -1
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +14 -26
- package/coverage/lcov-report/utilities/queue/index.html +17 -17
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +2 -2
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +1 -1
- package/coverage/lcov.info +1214 -695
- package/dist/api/controllers/deploy/index.js +0 -1
- package/dist/api/controllers/query/index.js +1 -1
- package/dist/api/controllers/query/validation.js +3 -3
- package/dist/api/controllers/row/internalSearch.js +16 -30
- package/dist/api/routes/utils/validators.js +1 -1
- package/dist/automations/utils.js +1 -47
- package/dist/constants/index.js +4 -1
- package/dist/db/utils.js +1 -14
- package/dist/integrations/base/sql.js +14 -43
- package/dist/package.json +8 -8
- package/dist/threads/automation.js +54 -147
- package/dist/threads/index.js +20 -27
- package/dist/threads/query.js +15 -23
- package/dist/threads/utils.js +24 -47
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/global.js +5 -24
- package/dist/utilities/queue/inMemoryQueue.js +0 -5
- package/package.json +9 -9
- package/src/api/controllers/deploy/index.ts +1 -6
- package/src/api/controllers/query/index.ts +1 -1
- package/src/api/controllers/query/validation.js +3 -3
- package/src/api/controllers/row/internalSearch.js +20 -35
- package/src/api/routes/tests/user.spec.js +0 -2
- package/src/api/routes/utils/validators.js +1 -1
- package/src/automations/steps/executeQuery.js +0 -1
- package/src/automations/tests/automation.spec.js +2 -2
- package/src/automations/utils.ts +1 -54
- package/src/constants/index.js +5 -2
- package/src/db/utils.js +0 -16
- package/src/definitions/datasource.ts +0 -3
- package/src/integrations/base/sql.ts +13 -44
- package/src/integrations/tests/sql.spec.js +4 -50
- package/src/middleware/tests/currentapp.spec.js +0 -11
- package/src/threads/{automation.ts → automation.js} +48 -172
- package/src/threads/index.ts +23 -31
- package/src/threads/{query.ts → query.js} +12 -32
- package/src/threads/{utils.ts → utils.js} +12 -31
- package/src/utilities/global.js +3 -21
- package/src/utilities/queue/inMemoryQueue.js +0 -4
- package/builder/assets/index.7ea7c069.js +0 -977
- package/dist/definitions/automations.js +0 -8
- package/dist/threads/definitions.js +0 -2
- package/src/definitions/automations.ts +0 -49
- package/src/threads/definitions.ts +0 -18
|
@@ -1,47 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import { default as automationUtils } from "../automations/automationUtils"
|
|
6
|
-
import { default as AutomationEmitter } from "../events/AutomationEmitter"
|
|
7
|
-
import { generateAutomationMetadataID, isProdAppID } from "../db/utils"
|
|
8
|
-
import { definitions as triggerDefs } from "../automations/triggerInfo"
|
|
9
|
-
import { AutomationErrors, MAX_AUTOMATION_RECURRING_ERRORS } from "../constants"
|
|
10
|
-
import { storeLog } from "../automations/logging"
|
|
11
|
-
import { Automation, AutomationStep, AutomationStatus } from "@budibase/types"
|
|
12
|
-
import {
|
|
13
|
-
LoopStep,
|
|
14
|
-
LoopStepTypes,
|
|
15
|
-
LoopInput,
|
|
16
|
-
AutomationEvent,
|
|
17
|
-
TriggerOutput,
|
|
18
|
-
AutomationContext,
|
|
19
|
-
AutomationMetadata,
|
|
20
|
-
} from "../definitions/automations"
|
|
21
|
-
import { WorkerCallback } from "./definitions"
|
|
22
|
-
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
|
23
|
-
const { logAlertWithInfo, logWarn } = require("@budibase/backend-core/logging")
|
|
1
|
+
require("./utils").threadSetup()
|
|
2
|
+
const actions = require("../automations/actions")
|
|
3
|
+
const automationUtils = require("../automations/automationUtils")
|
|
4
|
+
const AutomationEmitter = require("../events/AutomationEmitter")
|
|
24
5
|
const { processObject } = require("@budibase/string-templates")
|
|
6
|
+
const { DocumentTypes } = require("../db/utils")
|
|
7
|
+
const { definitions: triggerDefs } = require("../automations/triggerInfo")
|
|
8
|
+
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context")
|
|
9
|
+
const { AutomationErrors, LoopStepTypes } = require("../constants")
|
|
10
|
+
const { storeLog } = require("../automations/logging")
|
|
25
11
|
const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
|
|
26
12
|
const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
|
|
13
|
+
|
|
27
14
|
const CRON_STEP_ID = triggerDefs.CRON.stepId
|
|
28
|
-
const STOPPED_STATUS = { success: true, status:
|
|
15
|
+
const STOPPED_STATUS = { success: true, status: "STOPPED" }
|
|
29
16
|
const { cloneDeep } = require("lodash/fp")
|
|
30
17
|
const env = require("../environment")
|
|
31
18
|
|
|
32
|
-
function typecastForLooping(loopStep
|
|
19
|
+
function typecastForLooping(loopStep, input) {
|
|
33
20
|
if (!input || !input.binding) {
|
|
34
21
|
return null
|
|
35
22
|
}
|
|
23
|
+
const isArray = Array.isArray(input.binding),
|
|
24
|
+
isString = typeof input.binding === "string"
|
|
36
25
|
try {
|
|
37
26
|
switch (loopStep.inputs.option) {
|
|
38
27
|
case LoopStepTypes.ARRAY:
|
|
39
|
-
if (
|
|
28
|
+
if (isString) {
|
|
40
29
|
return JSON.parse(input.binding)
|
|
41
30
|
}
|
|
42
31
|
break
|
|
43
32
|
case LoopStepTypes.STRING:
|
|
44
|
-
if (
|
|
33
|
+
if (isArray) {
|
|
45
34
|
return input.binding.join(",")
|
|
46
35
|
}
|
|
47
36
|
break
|
|
@@ -52,7 +41,7 @@ function typecastForLooping(loopStep: LoopStep, input: LoopInput) {
|
|
|
52
41
|
return input.binding
|
|
53
42
|
}
|
|
54
43
|
|
|
55
|
-
function getLoopIterations(loopStep
|
|
44
|
+
function getLoopIterations(loopStep, input) {
|
|
56
45
|
const binding = typecastForLooping(loopStep, input)
|
|
57
46
|
if (!loopStep || !binding) {
|
|
58
47
|
return 1
|
|
@@ -68,24 +57,11 @@ function getLoopIterations(loopStep: LoopStep, input: LoopInput) {
|
|
|
68
57
|
* inputs and handles any outputs.
|
|
69
58
|
*/
|
|
70
59
|
class Orchestrator {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
_repeat?: { jobId: string; jobKey: string }
|
|
77
|
-
executionOutput: AutomationContext
|
|
78
|
-
|
|
79
|
-
constructor(automation: Automation, triggerOutput: TriggerOutput, opts: any) {
|
|
80
|
-
const metadata = triggerOutput.metadata
|
|
81
|
-
this._chainCount = metadata ? metadata.automationChainCount : 0
|
|
82
|
-
this._appId = triggerOutput.appId as string
|
|
83
|
-
if (opts?.repeat) {
|
|
84
|
-
this._repeat = {
|
|
85
|
-
jobId: opts.repeat.jobId,
|
|
86
|
-
jobKey: opts.repeat.key,
|
|
87
|
-
}
|
|
88
|
-
}
|
|
60
|
+
constructor(automation, triggerOutput = {}) {
|
|
61
|
+
this._metadata = triggerOutput.metadata
|
|
62
|
+
this._chainCount = this._metadata ? this._metadata.automationChainCount : 0
|
|
63
|
+
this._appId = triggerOutput.appId
|
|
64
|
+
this._app = null
|
|
89
65
|
const triggerStepId = automation.definition.trigger.stepId
|
|
90
66
|
triggerOutput = this.cleanupTriggerOutputs(triggerStepId, triggerOutput)
|
|
91
67
|
// remove from context
|
|
@@ -103,14 +79,14 @@ class Orchestrator {
|
|
|
103
79
|
this.updateExecutionOutput(triggerId, triggerStepId, null, triggerOutput)
|
|
104
80
|
}
|
|
105
81
|
|
|
106
|
-
cleanupTriggerOutputs(stepId
|
|
82
|
+
cleanupTriggerOutputs(stepId, triggerOutput) {
|
|
107
83
|
if (stepId === CRON_STEP_ID) {
|
|
108
84
|
triggerOutput.timestamp = Date.now()
|
|
109
85
|
}
|
|
110
86
|
return triggerOutput
|
|
111
87
|
}
|
|
112
88
|
|
|
113
|
-
async getStepFunctionality(stepId
|
|
89
|
+
async getStepFunctionality(stepId) {
|
|
114
90
|
let step = await actions.getAction(stepId)
|
|
115
91
|
if (step == null) {
|
|
116
92
|
throw `Cannot find automation step by name ${stepId}`
|
|
@@ -118,107 +94,25 @@ class Orchestrator {
|
|
|
118
94
|
return step
|
|
119
95
|
}
|
|
120
96
|
|
|
121
|
-
async
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
let metadata: AutomationMetadata
|
|
125
|
-
try {
|
|
126
|
-
metadata = await db.get(metadataId)
|
|
127
|
-
} catch (err) {
|
|
128
|
-
metadata = {
|
|
129
|
-
_id: metadataId,
|
|
130
|
-
errorCount: 0,
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
return metadata
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async checkIfShouldStop(metadata: AutomationMetadata): Promise<boolean> {
|
|
137
|
-
if (!metadata.errorCount || !this._repeat) {
|
|
138
|
-
return false
|
|
139
|
-
}
|
|
140
|
-
const automation = this._automation
|
|
141
|
-
const trigger = automation.definition.trigger
|
|
142
|
-
if (metadata.errorCount >= MAX_AUTOMATION_RECURRING_ERRORS) {
|
|
143
|
-
logWarn(
|
|
144
|
-
`CRON disabled due to errors - ${this._appId}/${this._automation._id}`
|
|
145
|
-
)
|
|
146
|
-
await disableCron(this._repeat?.jobId, this._repeat?.jobKey)
|
|
147
|
-
this.updateExecutionOutput(
|
|
148
|
-
trigger.id,
|
|
149
|
-
trigger.stepId,
|
|
150
|
-
{},
|
|
151
|
-
{
|
|
152
|
-
status: AutomationStatus.STOPPED_ERROR,
|
|
153
|
-
success: false,
|
|
154
|
-
}
|
|
155
|
-
)
|
|
156
|
-
await storeLog(automation, this.executionOutput)
|
|
157
|
-
return true
|
|
158
|
-
}
|
|
159
|
-
return false
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
async updateMetadata(metadata: AutomationMetadata) {
|
|
163
|
-
const output = this.executionOutput,
|
|
164
|
-
automation = this._automation
|
|
165
|
-
if (!output || !isRecurring(automation)) {
|
|
166
|
-
return
|
|
167
|
-
}
|
|
168
|
-
const count = metadata.errorCount
|
|
169
|
-
const isError = isErrorInOutput(output)
|
|
170
|
-
// nothing to do in this scenario, escape
|
|
171
|
-
if (!count && !isError) {
|
|
172
|
-
return
|
|
173
|
-
}
|
|
174
|
-
if (isError) {
|
|
175
|
-
metadata.errorCount = count ? count + 1 : 1
|
|
176
|
-
} else {
|
|
177
|
-
metadata.errorCount = 0
|
|
97
|
+
async getApp() {
|
|
98
|
+
if (this._app) {
|
|
99
|
+
return this._app
|
|
178
100
|
}
|
|
179
101
|
const db = getAppDB()
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
} catch (err) {
|
|
183
|
-
logAlertWithInfo(
|
|
184
|
-
"Failed to write automation metadata",
|
|
185
|
-
db.name,
|
|
186
|
-
automation._id,
|
|
187
|
-
err
|
|
188
|
-
)
|
|
189
|
-
}
|
|
102
|
+
this._app = await db.get(DocumentTypes.APP_METADATA)
|
|
103
|
+
return this._app
|
|
190
104
|
}
|
|
191
105
|
|
|
192
|
-
updateExecutionOutput(id
|
|
106
|
+
updateExecutionOutput(id, stepId, inputs, outputs) {
|
|
193
107
|
const stepObj = { id, stepId, inputs, outputs }
|
|
194
|
-
// replacing trigger when disabling CRON
|
|
195
|
-
if (
|
|
196
|
-
stepId === CRON_STEP_ID &&
|
|
197
|
-
outputs.status === AutomationStatus.STOPPED_ERROR
|
|
198
|
-
) {
|
|
199
|
-
this.executionOutput.trigger = stepObj
|
|
200
|
-
this.executionOutput.steps = [stepObj]
|
|
201
|
-
return
|
|
202
|
-
}
|
|
203
108
|
// first entry is always the trigger (constructor)
|
|
204
|
-
if (
|
|
205
|
-
this.executionOutput.steps.length === 0 ||
|
|
206
|
-
this.executionOutput.trigger.id === id
|
|
207
|
-
) {
|
|
109
|
+
if (this.executionOutput.steps.length === 0) {
|
|
208
110
|
this.executionOutput.trigger = stepObj
|
|
209
111
|
}
|
|
210
112
|
this.executionOutput.steps.push(stepObj)
|
|
211
113
|
}
|
|
212
114
|
|
|
213
|
-
updateContextAndOutput(
|
|
214
|
-
loopStepNumber: number | undefined,
|
|
215
|
-
step: AutomationStep,
|
|
216
|
-
output: any,
|
|
217
|
-
result: { success: boolean; status: string }
|
|
218
|
-
) {
|
|
219
|
-
if (!loopStepNumber) {
|
|
220
|
-
throw new Error("No loop step number provided.")
|
|
221
|
-
}
|
|
115
|
+
updateContextAndOutput(loopStepNumber, step, output, result) {
|
|
222
116
|
this.executionOutput.steps.splice(loopStepNumber, 0, {
|
|
223
117
|
id: step.id,
|
|
224
118
|
stepId: step.stepId,
|
|
@@ -239,22 +133,11 @@ class Orchestrator {
|
|
|
239
133
|
async execute() {
|
|
240
134
|
let automation = this._automation
|
|
241
135
|
let stopped = false
|
|
242
|
-
let loopStep
|
|
136
|
+
let loopStep = null
|
|
243
137
|
|
|
244
138
|
let stepCount = 0
|
|
245
|
-
let loopStepNumber
|
|
246
|
-
let loopSteps
|
|
247
|
-
let metadata
|
|
248
|
-
|
|
249
|
-
// check if this is a recurring automation,
|
|
250
|
-
if (isProdAppID(this._appId) && isRecurring(automation)) {
|
|
251
|
-
metadata = await this.getMetadata()
|
|
252
|
-
const shouldStop = await this.checkIfShouldStop(metadata)
|
|
253
|
-
if (shouldStop) {
|
|
254
|
-
return
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
139
|
+
let loopStepNumber = null
|
|
140
|
+
let loopSteps = []
|
|
258
141
|
for (let step of automation.definition.steps) {
|
|
259
142
|
stepCount++
|
|
260
143
|
let input,
|
|
@@ -268,7 +151,7 @@ class Orchestrator {
|
|
|
268
151
|
|
|
269
152
|
if (loopStep) {
|
|
270
153
|
input = await processObject(loopStep.inputs, this._context)
|
|
271
|
-
iterations = getLoopIterations(loopStep
|
|
154
|
+
iterations = getLoopIterations(loopStep, input)
|
|
272
155
|
}
|
|
273
156
|
|
|
274
157
|
for (let index = 0; index < iterations; index++) {
|
|
@@ -283,17 +166,14 @@ class Orchestrator {
|
|
|
283
166
|
|
|
284
167
|
let tempOutput = { items: loopSteps, iterations: iterationCount }
|
|
285
168
|
try {
|
|
286
|
-
newInput.binding = typecastForLooping(
|
|
287
|
-
loopStep as LoopStep,
|
|
288
|
-
newInput
|
|
289
|
-
)
|
|
169
|
+
newInput.binding = typecastForLooping(loopStep, newInput)
|
|
290
170
|
} catch (err) {
|
|
291
171
|
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
|
|
292
172
|
status: AutomationErrors.INCORRECT_TYPE,
|
|
293
173
|
success: false,
|
|
294
174
|
})
|
|
295
|
-
loopSteps =
|
|
296
|
-
loopStep =
|
|
175
|
+
loopSteps = null
|
|
176
|
+
loopStep = null
|
|
297
177
|
break
|
|
298
178
|
}
|
|
299
179
|
|
|
@@ -343,8 +223,8 @@ class Orchestrator {
|
|
|
343
223
|
status: AutomationErrors.MAX_ITERATIONS,
|
|
344
224
|
success: true,
|
|
345
225
|
})
|
|
346
|
-
loopSteps =
|
|
347
|
-
loopStep =
|
|
226
|
+
loopSteps = null
|
|
227
|
+
loopStep = null
|
|
348
228
|
break
|
|
349
229
|
}
|
|
350
230
|
|
|
@@ -352,7 +232,7 @@ class Orchestrator {
|
|
|
352
232
|
const currentItem = this._context.steps[loopStepNumber]?.currentItem
|
|
353
233
|
if (currentItem && typeof currentItem === "object") {
|
|
354
234
|
isFailure = Object.keys(currentItem).some(value => {
|
|
355
|
-
return currentItem[value] === loopStep
|
|
235
|
+
return currentItem[value] === loopStep.inputs.failure
|
|
356
236
|
})
|
|
357
237
|
} else {
|
|
358
238
|
isFailure = currentItem && currentItem === loopStep.inputs.failure
|
|
@@ -363,8 +243,8 @@ class Orchestrator {
|
|
|
363
243
|
status: AutomationErrors.FAILURE_CONDITION,
|
|
364
244
|
success: false,
|
|
365
245
|
})
|
|
366
|
-
loopSteps =
|
|
367
|
-
loopStep =
|
|
246
|
+
loopSteps = null
|
|
247
|
+
loopStep = null
|
|
368
248
|
break
|
|
369
249
|
}
|
|
370
250
|
}
|
|
@@ -415,7 +295,7 @@ class Orchestrator {
|
|
|
415
295
|
if (loopStep) {
|
|
416
296
|
iterationCount++
|
|
417
297
|
if (index === iterations - 1) {
|
|
418
|
-
loopStep =
|
|
298
|
+
loopStep = null
|
|
419
299
|
this._context.steps.splice(loopStepNumber, 1)
|
|
420
300
|
break
|
|
421
301
|
}
|
|
@@ -436,26 +316,22 @@ class Orchestrator {
|
|
|
436
316
|
})
|
|
437
317
|
|
|
438
318
|
this._context.steps.splice(loopStepNumber, 0, tempOutput)
|
|
439
|
-
loopSteps =
|
|
319
|
+
loopSteps = null
|
|
440
320
|
}
|
|
441
321
|
}
|
|
442
322
|
|
|
443
323
|
// store the logs for the automation run
|
|
444
324
|
await storeLog(this._automation, this.executionOutput)
|
|
445
|
-
if (isProdAppID(this._appId) && isRecurring(automation) && metadata) {
|
|
446
|
-
await this.updateMetadata(metadata)
|
|
447
|
-
}
|
|
448
325
|
return this.executionOutput
|
|
449
326
|
}
|
|
450
327
|
}
|
|
451
328
|
|
|
452
|
-
|
|
329
|
+
module.exports = (input, callback) => {
|
|
453
330
|
const appId = input.data.event.appId
|
|
454
331
|
doInAppContext(appId, async () => {
|
|
455
332
|
const automationOrchestrator = new Orchestrator(
|
|
456
333
|
input.data.automation,
|
|
457
|
-
input.data.event
|
|
458
|
-
input.opts
|
|
334
|
+
input.data.event
|
|
459
335
|
)
|
|
460
336
|
try {
|
|
461
337
|
const response = await automationOrchestrator.execute()
|
package/src/threads/index.ts
CHANGED
|
@@ -18,23 +18,26 @@ function typeToFile(type: any) {
|
|
|
18
18
|
default:
|
|
19
19
|
throw "Unknown thread type"
|
|
20
20
|
}
|
|
21
|
-
// have to use require here, to make it work with worker-farm
|
|
22
21
|
return require.resolve(filename)
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
export class Thread {
|
|
26
25
|
type: any
|
|
27
26
|
count: any
|
|
27
|
+
disableThreading: any
|
|
28
28
|
workers: any
|
|
29
29
|
timeoutMs: any
|
|
30
|
-
disableThreading: boolean
|
|
31
30
|
|
|
32
31
|
static workerRefs: any[] = []
|
|
33
32
|
|
|
34
33
|
constructor(type: any, opts: any = { timeoutMs: null, count: 1 }) {
|
|
35
34
|
this.type = type
|
|
36
35
|
this.count = opts.count ? opts.count : 1
|
|
37
|
-
this.disableThreading =
|
|
36
|
+
this.disableThreading =
|
|
37
|
+
env.isTest() ||
|
|
38
|
+
env.DISABLE_THREADING ||
|
|
39
|
+
this.count === 0 ||
|
|
40
|
+
env.isInThread()
|
|
38
41
|
if (!this.disableThreading) {
|
|
39
42
|
const workerOpts: any = {
|
|
40
43
|
autoStart: true,
|
|
@@ -44,44 +47,33 @@ export class Thread {
|
|
|
44
47
|
this.timeoutMs = opts.timeoutMs
|
|
45
48
|
workerOpts.maxCallTime = opts.timeoutMs
|
|
46
49
|
}
|
|
47
|
-
this.workers = workerFarm(workerOpts, typeToFile(type)
|
|
50
|
+
this.workers = workerFarm(workerOpts, typeToFile(type))
|
|
48
51
|
Thread.workerRefs.push(this.workers)
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
shouldDisableThreading(): boolean {
|
|
53
|
-
return !!(
|
|
54
|
-
env.isTest() ||
|
|
55
|
-
env.DISABLE_THREADING ||
|
|
56
|
-
this.count === 0 ||
|
|
57
|
-
env.isInThread()
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
55
|
run(data: any) {
|
|
62
|
-
const timeout = this.timeoutMs
|
|
63
56
|
return new Promise((resolve, reject) => {
|
|
64
|
-
|
|
65
|
-
worker.execute(data, (err: any, response: any) => {
|
|
66
|
-
if (err && err.type === "TimeoutError") {
|
|
67
|
-
reject(
|
|
68
|
-
new Error(`Query response time exceeded ${timeout}ms timeout.`)
|
|
69
|
-
)
|
|
70
|
-
} else if (err) {
|
|
71
|
-
reject(err)
|
|
72
|
-
} else {
|
|
73
|
-
resolve(response)
|
|
74
|
-
}
|
|
75
|
-
})
|
|
76
|
-
}
|
|
57
|
+
let fncToCall
|
|
77
58
|
// if in test then don't use threading
|
|
78
59
|
if (this.disableThreading) {
|
|
79
|
-
|
|
80
|
-
fire(thread)
|
|
81
|
-
})
|
|
60
|
+
fncToCall = require(typeToFile(this.type))
|
|
82
61
|
} else {
|
|
83
|
-
|
|
62
|
+
fncToCall = this.workers
|
|
84
63
|
}
|
|
64
|
+
fncToCall(data, (err: any, response: any) => {
|
|
65
|
+
if (err && err.type === "TimeoutError") {
|
|
66
|
+
reject(
|
|
67
|
+
new Error(
|
|
68
|
+
`Query response time exceeded ${this.timeoutMs}ms timeout.`
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
} else if (err) {
|
|
72
|
+
reject(err)
|
|
73
|
+
} else {
|
|
74
|
+
resolve(response)
|
|
75
|
+
}
|
|
76
|
+
})
|
|
85
77
|
})
|
|
86
78
|
}
|
|
87
79
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
const threadUtils = require("./utils")
|
|
2
2
|
threadUtils.threadSetup()
|
|
3
|
-
import { WorkerCallback, QueryEvent, QueryVariable } from "./definitions"
|
|
4
3
|
const ScriptRunner = require("../utilities/scriptRunner")
|
|
5
4
|
const { integrations } = require("../integrations")
|
|
6
5
|
const { processStringSync } = require("@budibase/string-templates")
|
|
@@ -20,22 +19,7 @@ const {
|
|
|
20
19
|
} = require("../integrations/queries/sql")
|
|
21
20
|
|
|
22
21
|
class QueryRunner {
|
|
23
|
-
|
|
24
|
-
queryVerb: string
|
|
25
|
-
queryId: string
|
|
26
|
-
fields: any
|
|
27
|
-
parameters: any
|
|
28
|
-
pagination: any
|
|
29
|
-
transformer: any
|
|
30
|
-
cachedVariables: any[]
|
|
31
|
-
ctx: any
|
|
32
|
-
queryResponse: any
|
|
33
|
-
noRecursiveQuery: boolean
|
|
34
|
-
hasRerun: boolean
|
|
35
|
-
hasRefreshedOAuth: boolean
|
|
36
|
-
hasDynamicVariables: boolean
|
|
37
|
-
|
|
38
|
-
constructor(input: QueryEvent, flags = { noRecursiveQuery: false }) {
|
|
22
|
+
constructor(input, flags = { noRecursiveQuery: false }) {
|
|
39
23
|
this.datasource = input.datasource
|
|
40
24
|
this.queryVerb = input.queryVerb
|
|
41
25
|
this.fields = input.fields
|
|
@@ -53,10 +37,9 @@ class QueryRunner {
|
|
|
53
37
|
this.queryResponse = {}
|
|
54
38
|
this.hasRerun = false
|
|
55
39
|
this.hasRefreshedOAuth = false
|
|
56
|
-
this.hasDynamicVariables = false
|
|
57
40
|
}
|
|
58
41
|
|
|
59
|
-
async execute()
|
|
42
|
+
async execute() {
|
|
60
43
|
let { datasource, fields, queryVerb, transformer } = this
|
|
61
44
|
|
|
62
45
|
let datasourceClone = cloneDeep(datasource)
|
|
@@ -69,7 +52,7 @@ class QueryRunner {
|
|
|
69
52
|
|
|
70
53
|
if (datasourceClone.config.authConfigs) {
|
|
71
54
|
datasourceClone.config.authConfigs =
|
|
72
|
-
datasourceClone.config.authConfigs.map(
|
|
55
|
+
datasourceClone.config.authConfigs.map(config => {
|
|
73
56
|
return enrichQueryFields(config, this.ctx)
|
|
74
57
|
})
|
|
75
58
|
}
|
|
@@ -155,8 +138,8 @@ class QueryRunner {
|
|
|
155
138
|
}
|
|
156
139
|
|
|
157
140
|
// map into JSON if just raw primitive here
|
|
158
|
-
if (rows.find(
|
|
159
|
-
rows = rows.map(
|
|
141
|
+
if (rows.find(row => typeof row !== "object")) {
|
|
142
|
+
rows = rows.map(value => ({ value }))
|
|
160
143
|
}
|
|
161
144
|
|
|
162
145
|
// get all the potential fields in the schema
|
|
@@ -169,7 +152,7 @@ class QueryRunner {
|
|
|
169
152
|
return { rows, keys, info, extra, pagination }
|
|
170
153
|
}
|
|
171
154
|
|
|
172
|
-
async runAnotherQuery(queryId
|
|
155
|
+
async runAnotherQuery(queryId, parameters) {
|
|
173
156
|
const db = getAppDB()
|
|
174
157
|
const query = await db.get(queryId)
|
|
175
158
|
const datasource = await db.get(query.datasourceId)
|
|
@@ -180,13 +163,12 @@ class QueryRunner {
|
|
|
180
163
|
fields: query.fields,
|
|
181
164
|
parameters,
|
|
182
165
|
transformer: query.transformer,
|
|
183
|
-
queryId,
|
|
184
166
|
},
|
|
185
167
|
{ noRecursiveQuery: true }
|
|
186
168
|
).execute()
|
|
187
169
|
}
|
|
188
170
|
|
|
189
|
-
async refreshOAuth2(ctx
|
|
171
|
+
async refreshOAuth2(ctx) {
|
|
190
172
|
const { oauth2, providerType, _id } = ctx.user
|
|
191
173
|
const { configId } = ctx.auth
|
|
192
174
|
|
|
@@ -218,7 +200,7 @@ class QueryRunner {
|
|
|
218
200
|
return resp
|
|
219
201
|
}
|
|
220
202
|
|
|
221
|
-
async getDynamicVariable(variable
|
|
203
|
+
async getDynamicVariable(variable) {
|
|
222
204
|
let { parameters } = this
|
|
223
205
|
const queryId = variable.queryId,
|
|
224
206
|
name = variable.name
|
|
@@ -251,7 +233,7 @@ class QueryRunner {
|
|
|
251
233
|
if (!this.noRecursiveQuery) {
|
|
252
234
|
// need to see if this uses any variables
|
|
253
235
|
const stringFields = JSON.stringify(fields)
|
|
254
|
-
const foundVars = dynamicVars.filter(
|
|
236
|
+
const foundVars = dynamicVars.filter(variable => {
|
|
255
237
|
// don't allow a query to use its own dynamic variable (loop)
|
|
256
238
|
if (variable.queryId === this.queryId) {
|
|
257
239
|
return false
|
|
@@ -260,9 +242,7 @@ class QueryRunner {
|
|
|
260
242
|
const regex = new RegExp(`{{[ ]*${variable.name}[ ]*}}`)
|
|
261
243
|
return regex.test(stringFields)
|
|
262
244
|
})
|
|
263
|
-
const dynamics = foundVars.map((dynVar
|
|
264
|
-
this.getDynamicVariable(dynVar)
|
|
265
|
-
)
|
|
245
|
+
const dynamics = foundVars.map(dynVar => this.getDynamicVariable(dynVar))
|
|
266
246
|
const responses = await Promise.all(dynamics)
|
|
267
247
|
for (let i = 0; i < foundVars.length; i++) {
|
|
268
248
|
const variable = foundVars[i]
|
|
@@ -284,7 +264,7 @@ class QueryRunner {
|
|
|
284
264
|
}
|
|
285
265
|
}
|
|
286
266
|
|
|
287
|
-
|
|
267
|
+
module.exports = (input, callback) => {
|
|
288
268
|
doInAppContext(input.appId, async () => {
|
|
289
269
|
const Runner = new QueryRunner(input)
|
|
290
270
|
try {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { QueryVariable } from "./definitions"
|
|
2
1
|
const env = require("../environment")
|
|
3
2
|
const db = require("../db")
|
|
4
3
|
const redis = require("@budibase/backend-core/redis")
|
|
5
4
|
const { SEPARATOR } = require("@budibase/backend-core/db")
|
|
6
5
|
|
|
7
6
|
const VARIABLE_TTL_SECONDS = 3600
|
|
8
|
-
let client
|
|
7
|
+
let client
|
|
9
8
|
|
|
10
9
|
async function getClient() {
|
|
11
10
|
if (!client) {
|
|
@@ -15,16 +14,10 @@ async function getClient() {
|
|
|
15
14
|
}
|
|
16
15
|
|
|
17
16
|
process.on("exit", async () => {
|
|
18
|
-
if (client)
|
|
19
|
-
await client.finish()
|
|
20
|
-
}
|
|
17
|
+
if (client) await client.finish()
|
|
21
18
|
})
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
return `${queryId}${SEPARATOR}${variable}`
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function threadSetup() {
|
|
20
|
+
exports.threadSetup = () => {
|
|
28
21
|
// don't run this if not threading
|
|
29
22
|
if (env.isTest() || env.DISABLE_THREADING) {
|
|
30
23
|
return
|
|
@@ -34,15 +27,16 @@ export function threadSetup() {
|
|
|
34
27
|
db.init()
|
|
35
28
|
}
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
queryId
|
|
39
|
-
|
|
40
|
-
|
|
30
|
+
function makeVariableKey(queryId, variable) {
|
|
31
|
+
return `${queryId}${SEPARATOR}${variable}`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.checkCacheForDynamicVariable = async (queryId, variable) => {
|
|
41
35
|
const cache = await getClient()
|
|
42
36
|
return cache.get(makeVariableKey(queryId, variable))
|
|
43
37
|
}
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
exports.invalidateDynamicVariables = async cachedVars => {
|
|
46
40
|
const cache = await getClient()
|
|
47
41
|
let promises = []
|
|
48
42
|
for (let variable of cachedVars) {
|
|
@@ -53,11 +47,7 @@ export async function invalidateDynamicVariables(cachedVars: QueryVariable[]) {
|
|
|
53
47
|
await Promise.all(promises)
|
|
54
48
|
}
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
queryId: string,
|
|
58
|
-
variable: string,
|
|
59
|
-
value: any
|
|
60
|
-
) {
|
|
50
|
+
exports.storeDynamicVariable = async (queryId, variable, value) => {
|
|
61
51
|
const cache = await getClient()
|
|
62
52
|
await cache.store(
|
|
63
53
|
makeVariableKey(queryId, variable),
|
|
@@ -66,7 +56,7 @@ export async function storeDynamicVariable(
|
|
|
66
56
|
)
|
|
67
57
|
}
|
|
68
58
|
|
|
69
|
-
|
|
59
|
+
exports.formatResponse = resp => {
|
|
70
60
|
if (typeof resp === "string") {
|
|
71
61
|
try {
|
|
72
62
|
resp = JSON.parse(resp)
|
|
@@ -77,7 +67,7 @@ export function formatResponse(resp: any) {
|
|
|
77
67
|
return resp
|
|
78
68
|
}
|
|
79
69
|
|
|
80
|
-
|
|
70
|
+
exports.hasExtraData = response => {
|
|
81
71
|
return (
|
|
82
72
|
typeof response === "object" &&
|
|
83
73
|
!Array.isArray(response) &&
|
|
@@ -86,12 +76,3 @@ export function hasExtraData(response: any) {
|
|
|
86
76
|
response.info != null
|
|
87
77
|
)
|
|
88
78
|
}
|
|
89
|
-
|
|
90
|
-
export default {
|
|
91
|
-
hasExtraData,
|
|
92
|
-
formatResponse,
|
|
93
|
-
storeDynamicVariable,
|
|
94
|
-
invalidateDynamicVariables,
|
|
95
|
-
checkCacheForDynamicVariable,
|
|
96
|
-
threadSetup,
|
|
97
|
-
}
|