refactor(core): Centralize CronJob management (#10033)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2024-07-16 20:42:48 +02:00
committed by GitHub
parent 36b314d031
commit 09f2cf9eaf
18 changed files with 730 additions and 429 deletions

View File

@@ -1,10 +1,10 @@
import type { CronExpression } from './Interfaces';
import { randomInt } from './utils';
interface BaseTriggerTime<T extends string> {
mode: T;
}
type CronExpression = string;
interface CustomTrigger extends BaseTriggerTime<'custom'> {
cronExpression: CronExpression;
}
@@ -49,22 +49,24 @@ export type TriggerTime =
| EveryWeek
| EveryMonth;
const randomSecond = () => randomInt(60).toString();
export const toCronExpression = (item: TriggerTime): CronExpression => {
if (item.mode === 'everyMinute') return `${randomSecond()} * * * * *`;
if (item.mode === 'everyHour') return `${randomSecond()} ${item.minute} * * * *`;
const randomSecond = randomInt(60);
if (item.mode === 'everyMinute') return `${randomSecond} * * * * *`;
if (item.mode === 'everyHour') return `${randomSecond} ${item.minute} * * * *`;
if (item.mode === 'everyX') {
if (item.unit === 'minutes') return `${randomSecond()} */${item.value} * * * *`;
if (item.unit === 'hours') return `${randomSecond()} 0 */${item.value} * * *`;
if (item.unit === 'minutes') return `${randomSecond} */${item.value} * * * *`;
const randomMinute = randomInt(60);
if (item.unit === 'hours') return `${randomSecond} ${randomMinute} */${item.value} * * *`;
}
if (item.mode === 'everyDay') return `${randomSecond()} ${item.minute} ${item.hour} * * *`;
if (item.mode === 'everyDay') return `${randomSecond} ${item.minute} ${item.hour} * * *`;
if (item.mode === 'everyWeek')
return `${randomSecond()} ${item.minute} ${item.hour} * * ${item.weekday}`;
return `${randomSecond} ${item.minute} ${item.hour} * * ${item.weekday}`;
if (item.mode === 'everyMonth')
return `${randomSecond()} ${item.minute} ${item.hour} ${item.dayOfMonth} * *`;
return `${randomSecond} ${item.minute} ${item.hour} ${item.dayOfMonth} * *`;
return item.cronExpression.trim();
return item.cronExpression.trim() as CronExpression;
};

View File

@@ -842,6 +842,14 @@ export interface SSHTunnelFunctions {
getSSHClient(credentials: SSHCredentials): Promise<SSHClient>;
}
type CronUnit = number | '*' | `*/${number}`;
export type CronExpression =
`${CronUnit} ${CronUnit} ${CronUnit} ${CronUnit} ${CronUnit} ${CronUnit}`;
export interface SchedulingFunctions {
registerCron(cronExpression: CronExpression, onTick: () => void): void;
}
export type NodeTypeAndVersion = {
name: string;
type: string;
@@ -994,6 +1002,7 @@ export interface IPollFunctions
helpers: RequestHelperFunctions &
BaseHelperFunctions &
BinaryHelperFunctions &
SchedulingFunctions &
JsonHelperFunctions;
}
@@ -1014,6 +1023,7 @@ export interface ITriggerFunctions
BaseHelperFunctions &
BinaryHelperFunctions &
SSHTunnelFunctions &
SchedulingFunctions &
JsonHelperFunctions;
}
@@ -1436,14 +1446,10 @@ export type IParameterLabel = {
size?: 'small' | 'medium';
};
export interface IPollResponse {
closeFunction?: CloseFunction;
}
export interface ITriggerResponse {
closeFunction?: CloseFunction;
// To manually trigger the run
manualTriggerFunction?: CloseFunction;
manualTriggerFunction?: () => Promise<void>;
// Gets added automatically at manual workflow runs resolves with
// the first emitted data
manualTriggerResponse?: Promise<INodeExecutionData[][]>;

View File

@@ -58,6 +58,7 @@ import {
STARTING_NODE_TYPES,
} from './Constants';
import { ApplicationError } from './errors/application.error';
import { getGlobalState } from './GlobalState';
function dedupe<T>(arr: T[]): T[] {
return [...new Set(arr)];
@@ -94,6 +95,8 @@ export class Workflow {
settings: IWorkflowSettings;
readonly timezone: string;
// To save workflow specific static data like for example
// ids of registered webhooks of nodes
staticData: IDataObject;
@@ -151,6 +154,7 @@ export class Workflow {
});
this.settings = parameters.settings || {};
this.timezone = this.settings.timezone ?? getGlobalState().defaultTimezone;
this.expression = new Expression(this);
}

View File

@@ -1,4 +1,5 @@
import { toCronExpression } from '@/Cron';
import type { CronExpression } from '@/Interfaces';
describe('Cron', () => {
describe('toCronExpression', () => {
@@ -6,7 +7,7 @@ describe('Cron', () => {
const expression = toCronExpression({
mode: 'everyMinute',
});
expect(expression).toMatch(/^[1-6]?[0-9] \* \* \* \* \*$/);
expect(expression).toMatch(/^[1-5]?[0-9] \* \* \* \* \*$/);
});
test('should generate a valid cron for `everyHour` triggers', () => {
@@ -14,7 +15,7 @@ describe('Cron', () => {
mode: 'everyHour',
minute: 11,
});
expect(expression).toMatch(/^[1-6]?[0-9] 11 \* \* \* \*$/);
expect(expression).toMatch(/^[1-5]?[0-9] 11 \* \* \* \*$/);
});
test('should generate a valid cron for `everyX[minutes]` triggers', () => {
@@ -23,7 +24,7 @@ describe('Cron', () => {
unit: 'minutes',
value: 42,
});
expect(expression).toMatch(/^[1-6]?[0-9] \*\/42 \* \* \* \*$/);
expect(expression).toMatch(/^[1-5]?[0-9] \*\/42 \* \* \* \*$/);
});
test('should generate a valid cron for `everyX[hours]` triggers', () => {
@@ -32,7 +33,7 @@ describe('Cron', () => {
unit: 'hours',
value: 3,
});
expect(expression).toMatch(/^[1-6]?[0-9] 0 \*\/3 \* \* \*$/);
expect(expression).toMatch(/^[1-5]?[0-9] [1-5]?[0-9] \*\/3 \* \* \*$/);
});
test('should generate a valid cron for `everyDay` triggers', () => {
@@ -41,7 +42,7 @@ describe('Cron', () => {
hour: 13,
minute: 17,
});
expect(expression).toMatch(/^[1-6]?[0-9] 17 13 \* \* \*$/);
expect(expression).toMatch(/^[1-5]?[0-9] 17 13 \* \* \*$/);
});
test('should generate a valid cron for `everyWeek` triggers', () => {
@@ -51,7 +52,7 @@ describe('Cron', () => {
minute: 17,
weekday: 4,
});
expect(expression).toMatch(/^[1-6]?[0-9] 17 13 \* \* 4$/);
expect(expression).toMatch(/^[1-5]?[0-9] 17 13 \* \* 4$/);
});
test('should generate a valid cron for `everyMonth` triggers', () => {
@@ -61,13 +62,13 @@ describe('Cron', () => {
minute: 17,
dayOfMonth: 12,
});
expect(expression).toMatch(/^[1-6]?[0-9] 17 13 12 \* \*$/);
expect(expression).toMatch(/^[1-5]?[0-9] 17 13 12 \* \*$/);
});
test('should trim custom cron expressions', () => {
const expression = toCronExpression({
mode: 'custom',
cronExpression: ' 0 9-17 * * * ',
cronExpression: ' 0 9-17 * * * ' as CronExpression,
});
expect(expression).toEqual('0 9-17 * * *');
});