Merge branch 'chore/sqs-always-on' of github.com:budibase/budibase into split-server-tests-out-by-database

This commit is contained in:
Sam Rose 2024-11-07 10:16:57 +00:00
commit c418ffc8a9
No known key found for this signature in database
7 changed files with 93 additions and 7 deletions

View File

@ -1,6 +1,6 @@
{ {
"$schema": "node_modules/lerna/schemas/lerna-schema.json", "$schema": "node_modules/lerna/schemas/lerna-schema.json",
"version": "3.1.2", "version": "3.2.0",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*", "packages/*",

View File

@ -270,8 +270,8 @@ export const flags = new FlagSet({
[FeatureFlag.DEFAULT_VALUES]: Flag.boolean(true), [FeatureFlag.DEFAULT_VALUES]: Flag.boolean(true),
[FeatureFlag.AUTOMATION_BRANCHING]: Flag.boolean(true), [FeatureFlag.AUTOMATION_BRANCHING]: Flag.boolean(true),
[FeatureFlag.ENRICHED_RELATIONSHIPS]: Flag.boolean(true), [FeatureFlag.ENRICHED_RELATIONSHIPS]: Flag.boolean(true),
[FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(env.isDev()), [FeatureFlag.AI_CUSTOM_CONFIGS]: Flag.boolean(true),
[FeatureFlag.BUDIBASE_AI]: Flag.boolean(env.isDev()), [FeatureFlag.BUDIBASE_AI]: Flag.boolean(true),
}) })
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T type UnwrapPromise<T> = T extends Promise<infer U> ? U : T

View File

@ -141,7 +141,7 @@ class InMemoryQueue implements Partial<Queue> {
} else { } else {
pushMessage() pushMessage()
} }
return {} as any return { id: jobId } as any
} }
/** /**

View File

@ -0,0 +1,49 @@
import tk from "timekeeper"
import "../../environment"
import * as automations from "../index"
import * as setup from "./utilities"
import { basicCronAutomation } from "../../tests/utilities/structures"
const initialTime = Date.now()
tk.freeze(initialTime)
const oneMinuteInMs = 60 * 1000
describe("cron automations", () => {
let config = setup.getConfig()
beforeAll(async () => {
await automations.init()
await config.init()
})
afterAll(async () => {
await automations.shutdown()
setup.afterAll()
})
beforeEach(() => {
tk.freeze(initialTime)
})
async function travel(ms: number) {
tk.travel(Date.now() + ms)
}
it("should initialise the automation timestamp", async () => {
const automation = basicCronAutomation(config.appId!, "* * * * *")
await config.api.automation.post(automation)
await travel(oneMinuteInMs)
await config.publish()
const automationLogs = await config.getAutomationLogs()
expect(automationLogs.data).toHaveLength(1)
expect(automationLogs.data).toEqual([
expect.objectContaining({
trigger: expect.objectContaining({
outputs: { timestamp: initialTime + oneMinuteInMs },
}),
}),
])
})
})

View File

@ -70,6 +70,10 @@ export async function processEvent(job: AutomationJob) {
const task = async () => { const task = async () => {
try { try {
if (isCronTrigger(job.data.automation)) {
// Requires the timestamp at run time
job.data.event.timestamp = Date.now()
}
// need to actually await these so that an error can be captured properly // need to actually await these so that an error can be captured properly
console.log("automation running", ...loggingArgs(job)) console.log("automation running", ...loggingArgs(job))
@ -210,15 +214,15 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
} }
// make a job id rather than letting Bull decide, makes it easier to handle on way out // make a job id rather than letting Bull decide, makes it easier to handle on way out
const jobId = `${appId}_cron_${utils.newid()}` const jobId = `${appId}_cron_${utils.newid()}`
const job: any = await automationQueue.add( const job = await automationQueue.add(
{ {
automation, automation,
event: { appId, timestamp: Date.now() }, event: { appId },
}, },
{ repeat: { cron: cronExp }, jobId } { repeat: { cron: cronExp }, jobId }
) )
// Assign cron job ID from bull so we can remove it later if the cron trigger is removed // Assign cron job ID from bull so we can remove it later if the cron trigger is removed
trigger.cronJobId = job.id trigger.cronJobId = job.id.toString()
// can't use getAppDB here as this is likely to be called from dev app, // can't use getAppDB here as this is likely to be called from dev app,
// but this call could be for dev app or prod app, need to just use what // but this call could be for dev app or prod app, need to just use what
// was passed in // was passed in

View File

@ -245,6 +245,38 @@ export function basicAutomation(appId?: string): Automation {
} }
} }
export function basicCronAutomation(appId: string, cron: string): Automation {
const automation: Automation = {
name: `Automation ${generator.guid()}`,
definition: {
trigger: {
stepId: AutomationTriggerStepId.CRON,
name: "test",
tagline: "test",
icon: "test",
description: "test",
type: AutomationStepType.TRIGGER,
id: "test",
inputs: {
cron,
},
schema: {
inputs: {
properties: {},
},
outputs: {
properties: {},
},
},
},
steps: [],
},
type: "automation",
appId,
}
return automation
}
export function serverLogAutomation(appId?: string): Automation { export function serverLogAutomation(appId?: string): Automation {
return { return {
name: "My Automation", name: "My Automation",

View File

@ -14,6 +14,7 @@ export interface AutomationDataEvent {
row?: Row row?: Row
oldRow?: Row oldRow?: Row
user?: UserBindings user?: UserBindings
timestamp?: number
} }
export interface AutomationData { export interface AutomationData {