Merge pull request #14581 from Budibase/fix/invalid-row-triggers
Fix for row automation triggers when table deleted
This commit is contained in:
commit
bce1069ea4
|
@ -18,6 +18,7 @@ import {
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
AutomationStoppedReason,
|
AutomationStoppedReason,
|
||||||
AutomationStatus,
|
AutomationStatus,
|
||||||
|
AutomationRowEvent,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { executeInThread } from "../threads/automation"
|
import { executeInThread } from "../threads/automation"
|
||||||
import { dataFilters, sdk } from "@budibase/shared-core"
|
import { dataFilters, sdk } from "@budibase/shared-core"
|
||||||
|
@ -28,6 +29,7 @@ const JOB_OPTS = {
|
||||||
removeOnFail: true,
|
removeOnFail: true,
|
||||||
}
|
}
|
||||||
import * as automationUtils from "../automations/automationUtils"
|
import * as automationUtils from "../automations/automationUtils"
|
||||||
|
import { doesTableExist } from "../sdk/app/tables/getters"
|
||||||
|
|
||||||
async function getAllAutomations() {
|
async function getAllAutomations() {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
|
@ -38,25 +40,35 @@ async function getAllAutomations() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function queueRelevantRowAutomations(
|
async function queueRelevantRowAutomations(
|
||||||
event: { appId: string; row: Row; oldRow: Row },
|
event: AutomationRowEvent,
|
||||||
eventType: string
|
eventType: AutomationEventType
|
||||||
) {
|
) {
|
||||||
|
const tableId = event.row.tableId
|
||||||
if (event.appId == null) {
|
if (event.appId == null) {
|
||||||
throw `No appId specified for ${eventType} - check event emitters.`
|
throw `No appId specified for ${eventType} - check event emitters.`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// make sure table exists and is valid before proceeding
|
||||||
|
if (!tableId || !(await doesTableExist(tableId))) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
await context.doInAppContext(event.appId, async () => {
|
await context.doInAppContext(event.appId, async () => {
|
||||||
let automations = await getAllAutomations()
|
let automations = await getAllAutomations()
|
||||||
|
|
||||||
// filter down to the correct event type and enabled automations
|
// filter down to the correct event type and enabled automations
|
||||||
|
// make sure it is the correct table ID as well
|
||||||
automations = automations.filter(automation => {
|
automations = automations.filter(automation => {
|
||||||
const trigger = automation.definition.trigger
|
const trigger = automation.definition.trigger
|
||||||
return trigger && trigger.event === eventType && !automation.disabled
|
return (
|
||||||
|
trigger &&
|
||||||
|
trigger.event === eventType &&
|
||||||
|
!automation.disabled &&
|
||||||
|
trigger?.inputs?.tableId === event.row.tableId
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
for (const automation of automations) {
|
for (const automation of automations) {
|
||||||
const automationDef = automation.definition
|
|
||||||
const automationTrigger = automationDef?.trigger
|
|
||||||
// don't queue events which are for dev apps, only way to test automations is
|
// don't queue events which are for dev apps, only way to test automations is
|
||||||
// running tests on them, in production the test flag will never
|
// running tests on them, in production the test flag will never
|
||||||
// be checked due to lazy evaluation (first always false)
|
// be checked due to lazy evaluation (first always false)
|
||||||
|
@ -72,11 +84,7 @@ async function queueRelevantRowAutomations(
|
||||||
row: event.row,
|
row: event.row,
|
||||||
oldRow: event.oldRow,
|
oldRow: event.oldRow,
|
||||||
})
|
})
|
||||||
if (
|
if (shouldTrigger) {
|
||||||
automationTrigger?.inputs &&
|
|
||||||
automationTrigger.inputs.tableId === event.row.tableId &&
|
|
||||||
shouldTrigger
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
await automationQueue.add({ automation, event }, JOB_OPTS)
|
await automationQueue.add({ automation, event }, JOB_OPTS)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -87,6 +95,17 @@ async function queueRelevantRowAutomations(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function queueRowAutomations(
|
||||||
|
event: AutomationRowEvent,
|
||||||
|
type: AutomationEventType
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
await queueRelevantRowAutomations(event, type)
|
||||||
|
} catch (err: any) {
|
||||||
|
logging.logWarn("Unable to process row event", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emitter.on(
|
emitter.on(
|
||||||
AutomationEventType.ROW_SAVE,
|
AutomationEventType.ROW_SAVE,
|
||||||
async function (event: UpdatedRowEventEmitter) {
|
async function (event: UpdatedRowEventEmitter) {
|
||||||
|
@ -94,7 +113,7 @@ emitter.on(
|
||||||
if (!event || !event.row || !event.row.tableId) {
|
if (!event || !event.row || !event.row.tableId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_SAVE)
|
await queueRowAutomations(event, AutomationEventType.ROW_SAVE)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -103,7 +122,7 @@ emitter.on(AutomationEventType.ROW_UPDATE, async function (event) {
|
||||||
if (!event || !event.row || !event.row.tableId) {
|
if (!event || !event.row || !event.row.tableId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_UPDATE)
|
await queueRowAutomations(event, AutomationEventType.ROW_UPDATE)
|
||||||
})
|
})
|
||||||
|
|
||||||
emitter.on(AutomationEventType.ROW_DELETE, async function (event) {
|
emitter.on(AutomationEventType.ROW_DELETE, async function (event) {
|
||||||
|
@ -111,7 +130,7 @@ emitter.on(AutomationEventType.ROW_DELETE, async function (event) {
|
||||||
if (!event || !event.row || !event.row.tableId) {
|
if (!event || !event.row || !event.row.tableId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
await queueRelevantRowAutomations(event, AutomationEventType.ROW_DELETE)
|
await queueRowAutomations(event, AutomationEventType.ROW_DELETE)
|
||||||
})
|
})
|
||||||
|
|
||||||
function rowPassesFilters(row: Row, filters: SearchFilters) {
|
function rowPassesFilters(row: Row, filters: SearchFilters) {
|
||||||
|
|
|
@ -101,6 +101,15 @@ export async function getTable(tableId: string): Promise<Table> {
|
||||||
return await processTable(output)
|
return await processTable(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function doesTableExist(tableId: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const table = await getTable(tableId)
|
||||||
|
return !!table
|
||||||
|
} catch (err) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function getAllTables() {
|
export async function getAllTables() {
|
||||||
const [internal, external] = await Promise.all([
|
const [internal, external] = await Promise.all([
|
||||||
getAllInternalTables(),
|
getAllInternalTables(),
|
||||||
|
|
|
@ -15,4 +15,10 @@ export interface AutomationData {
|
||||||
automation: Automation
|
automation: Automation
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface AutomationRowEvent {
|
||||||
|
appId: string
|
||||||
|
row: Row
|
||||||
|
oldRow: Row
|
||||||
|
}
|
||||||
|
|
||||||
export type AutomationJob = Job<AutomationData>
|
export type AutomationJob = Job<AutomationData>
|
||||||
|
|
Loading…
Reference in New Issue