[N8N-4339] Unify all Cron-specific code. Improve typing, and add tests. (#3887)

This commit is contained in:
कारतोफ्फेलस्क्रिप्ट™
2022-08-19 12:45:04 +02:00
committed by GitHub
parent e53d5d9cc1
commit dc8f8b7874
9 changed files with 354 additions and 754 deletions

View File

@@ -1,17 +1,15 @@
import { ITriggerFunctions } from 'n8n-core';
import { INodeType, INodeTypeDescription, ITriggerResponse } from 'n8n-workflow';
import {
INodeType,
INodeTypeDescription,
ITriggerResponse,
NodeHelpers,
toCronExpression,
TriggerTime,
} from 'n8n-workflow';
import { CronJob } from 'cron';
interface TriggerTime {
mode: string;
hour: number;
minute: number;
dayOfMonth: number;
weekeday: number;
[key: string]: string | number;
}
export class Cron implements INodeType {
description: INodeTypeDescription = {
displayName: 'Cron',
@@ -49,194 +47,7 @@ export class Cron implements INodeType {
default: {},
description: 'Triggers for the workflow',
placeholder: 'Add Cron Time',
options: [
{
name: 'item',
displayName: 'Item',
values: [
{
displayName: 'Mode',
name: 'mode',
type: 'options',
// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items
options: [
{
name: 'Every Minute',
value: 'everyMinute',
},
{
name: 'Every Hour',
value: 'everyHour',
},
{
name: 'Every Day',
value: 'everyDay',
},
{
name: 'Every Week',
value: 'everyWeek',
},
{
name: 'Every Month',
value: 'everyMonth',
},
{
name: 'Every X',
value: 'everyX',
},
{
name: 'Custom',
value: 'custom',
},
],
default: 'everyDay',
description: 'How often to trigger',
},
{
displayName: 'Hour',
name: 'hour',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 23,
},
displayOptions: {
hide: {
mode: ['custom', 'everyHour', 'everyMinute', 'everyX'],
},
},
default: 14,
description: 'The hour of the day to trigger (24h format)',
},
{
displayName: 'Minute',
name: 'minute',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 59,
},
displayOptions: {
hide: {
mode: ['custom', 'everyMinute', 'everyX'],
},
},
default: 0,
description: 'The minute of the day to trigger',
},
{
displayName: 'Day of Month',
name: 'dayOfMonth',
type: 'number',
displayOptions: {
show: {
mode: ['everyMonth'],
},
},
typeOptions: {
minValue: 1,
maxValue: 31,
},
default: 1,
description: 'The day of the month to trigger',
},
{
displayName: 'Weekday',
name: 'weekday',
type: 'options',
displayOptions: {
show: {
mode: ['everyWeek'],
},
},
// eslint-disable-next-line n8n-nodes-base/node-param-options-type-unsorted-items
options: [
{
name: 'Monday',
value: '1',
},
{
name: 'Tuesday',
value: '2',
},
{
name: 'Wednesday',
value: '3',
},
{
name: 'Thursday',
value: '4',
},
{
name: 'Friday',
value: '5',
},
{
name: 'Saturday',
value: '6',
},
{
name: 'Sunday',
value: '0',
},
],
default: '1',
description: 'The weekday to trigger',
},
{
displayName: 'Cron Expression',
name: 'cronExpression',
type: 'string',
displayOptions: {
show: {
mode: ['custom'],
},
},
default: '* * * * * *',
description:
'Use custom cron expression. Values and ranges as follows:<ul><li>Seconds: 0-59</li><li>Minutes: 0 - 59</li><li>Hours: 0 - 23</li><li>Day of Month: 1 - 31</li><li>Months: 0 - 11 (Jan - Dec)</li><li>Day of Week: 0 - 6 (Sun - Sat)</li></ul>.',
},
{
displayName: 'Value',
name: 'value',
type: 'number',
typeOptions: {
minValue: 0,
maxValue: 1000,
},
displayOptions: {
show: {
mode: ['everyX'],
},
},
default: 2,
description: 'All how many X minutes/hours it should trigger',
},
{
displayName: 'Unit',
name: 'unit',
type: 'options',
displayOptions: {
show: {
mode: ['everyX'],
},
},
options: [
{
name: 'Minutes',
value: 'minutes',
},
{
name: 'Hours',
value: 'hours',
},
],
default: 'hours',
description: 'If it should trigger all X minutes or hours',
},
],
},
],
options: NodeHelpers.cronNodeOptions,
},
],
};
@@ -246,57 +57,8 @@ export class Cron implements INodeType {
item: TriggerTime[];
};
// Define the order the cron-time-parameter appear
const parameterOrder = [
'second', // 0 - 59
'minute', // 0 - 59
'hour', // 0 - 23
'dayOfMonth', // 1 - 31
'month', // 0 - 11(Jan - Dec)
'weekday', // 0 - 6(Sun - Sat)
];
// Get all the trigger times
const cronTimes: string[] = [];
let cronTime: string[];
let parameterName: string;
if (triggerTimes.item !== undefined) {
for (const item of triggerTimes.item) {
cronTime = [];
if (item.mode === 'custom') {
cronTimes.push(item.cronExpression as string);
continue;
}
if (item.mode === 'everyMinute') {
cronTimes.push(`${Math.floor(Math.random() * 60).toString()} * * * * *`);
continue;
}
if (item.mode === 'everyX') {
if (item.unit === 'minutes') {
cronTimes.push(`${Math.floor(Math.random() * 60).toString()} */${item.value} * * * *`);
} else if (item.unit === 'hours') {
cronTimes.push(`${Math.floor(Math.random() * 60).toString()} 0 */${item.value} * * *`);
}
continue;
}
for (parameterName of parameterOrder) {
if (item[parameterName] !== undefined) {
// Value is set so use it
cronTime.push(item[parameterName] as string);
} else if (parameterName === 'second') {
// For seconds we use by default a random one to make sure to
// balance the load a little bit over time
cronTime.push(Math.floor(Math.random() * 60).toString());
} else {
// For all others set "any"
cronTime.push('*');
}
}
cronTimes.push(cronTime.join(' '));
}
}
const cronTimes = (triggerTimes.item || []).map(toCronExpression);
// The trigger function to execute when the cron-time got reached
// or when manually triggered
@@ -307,10 +69,7 @@ export class Cron implements INodeType {
const timezone = this.getTimezone();
// Start the cron-jobs
const cronJobs: CronJob[] = [];
for (const cronTime of cronTimes) {
cronJobs.push(new CronJob(cronTime, executeTrigger, undefined, true, timezone));
}
const cronJobs = cronTimes.map(cronTime => new CronJob(cronTime, executeTrigger, undefined, true, timezone));
// Stop the cron-jobs
async function closeFunction() {