@n8n/scheduler 0.2.3 → 0.3.0
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/README.md +60 -23
- package/dist/build.tsbuildinfo +1 -1
- package/dist/core/errors.d.ts +6 -0
- package/dist/core/errors.js +15 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/core/executor/backoff.js.map +1 -0
- package/dist/core/executor/executor.d.ts +38 -0
- package/dist/core/executor/executor.js +137 -0
- package/dist/core/executor/executor.js.map +1 -0
- package/dist/core/executor/index.d.ts +8 -0
- package/dist/core/executor/index.js +16 -0
- package/dist/core/executor/index.js.map +1 -0
- package/dist/core/executor/options.d.ts +6 -0
- package/dist/core/executor/options.js +10 -0
- package/dist/core/executor/options.js.map +1 -0
- package/dist/{executor → core/executor}/precision-timer.d.ts +1 -0
- package/dist/{executor → core/executor}/precision-timer.js +3 -0
- package/dist/core/executor/precision-timer.js.map +1 -0
- package/dist/core/executor/store.d.ts +21 -0
- package/dist/core/executor/store.js +3 -0
- package/dist/core/executor/store.js.map +1 -0
- package/dist/{executor → core/executor}/task-handler.d.ts +1 -1
- package/dist/{executor → core/executor}/task-handler.js +2 -2
- package/dist/core/executor/task-handler.js.map +1 -0
- package/dist/core/executor/tracing.d.ts +11 -0
- package/dist/core/executor/tracing.js +7 -0
- package/dist/core/executor/tracing.js.map +1 -0
- package/dist/core/factory.d.ts +29 -0
- package/dist/core/factory.js +254 -0
- package/dist/core/factory.js.map +1 -0
- package/dist/core/index.d.ts +17 -9
- package/dist/core/index.js +15 -17
- package/dist/core/index.js.map +1 -1
- package/dist/core/lifecycle/alarm.d.ts +8 -0
- package/dist/core/lifecycle/alarm.js +32 -0
- package/dist/core/lifecycle/alarm.js.map +1 -0
- package/dist/core/lifecycle/index.d.ts +5 -0
- package/dist/core/lifecycle/index.js +11 -0
- package/dist/core/lifecycle/index.js.map +1 -0
- package/dist/core/lifecycle/lookahead.d.ts +1 -0
- package/dist/core/lifecycle/lookahead.js +7 -0
- package/dist/core/lifecycle/lookahead.js.map +1 -0
- package/dist/core/lifecycle/loop.d.ts +39 -0
- package/dist/core/lifecycle/loop.js +86 -0
- package/dist/core/lifecycle/loop.js.map +1 -0
- package/dist/core/lifecycle/options.d.ts +15 -0
- package/dist/core/lifecycle/options.js +18 -0
- package/dist/core/lifecycle/options.js.map +1 -0
- package/dist/core/lifecycle/timeline.d.ts +9 -0
- package/dist/core/lifecycle/timeline.js +22 -0
- package/dist/core/lifecycle/timeline.js.map +1 -0
- package/dist/core/materializer/index.d.ts +2 -2
- package/dist/core/materializer/index.js.map +1 -1
- package/dist/core/materializer/materialize.d.ts +10 -2
- package/dist/core/materializer/materialize.js +32 -6
- package/dist/core/materializer/materialize.js.map +1 -1
- package/dist/core/materializer/options.d.ts +1 -0
- package/dist/core/materializer/options.js +1 -0
- package/dist/core/materializer/options.js.map +1 -1
- package/dist/core/materializer/plan.d.ts +1 -0
- package/dist/core/materializer/plan.js +12 -6
- package/dist/core/materializer/plan.js.map +1 -1
- package/dist/core/materializer/transaction.d.ts +18 -1
- package/dist/core/provisioning/index.d.ts +5 -0
- package/dist/core/provisioning/index.js +9 -0
- package/dist/core/provisioning/index.js.map +1 -0
- package/dist/core/provisioning/provision.d.ts +6 -0
- package/dist/core/provisioning/provision.js +64 -0
- package/dist/core/provisioning/provision.js.map +1 -0
- package/dist/core/provisioning/provisioner.d.ts +15 -0
- package/dist/core/provisioning/provisioner.js +18 -0
- package/dist/core/provisioning/provisioner.js.map +1 -0
- package/dist/core/provisioning/transaction.d.ts +13 -0
- package/dist/core/provisioning/transaction.js +3 -0
- package/dist/core/provisioning/transaction.js.map +1 -0
- package/dist/core/provisioning/types.d.ts +43 -0
- package/dist/core/provisioning/types.js +3 -0
- package/dist/core/provisioning/types.js.map +1 -0
- package/dist/core/reaper/index.d.ts +1 -0
- package/dist/core/reaper/index.js +7 -0
- package/dist/core/reaper/index.js.map +1 -0
- package/dist/{reaper/reaper.d.ts → core/reaper/reap.d.ts} +13 -8
- package/dist/core/reaper/reap.js +51 -0
- package/dist/core/reaper/reap.js.map +1 -0
- package/dist/core/recurrence/field.d.ts +2 -0
- package/dist/core/recurrence/field.js +12 -0
- package/dist/core/recurrence/field.js.map +1 -0
- package/dist/core/recurrence/kinds/cron.d.ts +10 -0
- package/dist/core/recurrence/kinds/cron.js +64 -0
- package/dist/core/recurrence/kinds/cron.js.map +1 -0
- package/dist/core/recurrence/kinds/interval.d.ts +5 -0
- package/dist/core/recurrence/kinds/interval.js +29 -0
- package/dist/core/recurrence/kinds/interval.js.map +1 -0
- package/dist/core/recurrence/kinds/one-off.d.ts +5 -0
- package/dist/core/recurrence/kinds/one-off.js +24 -0
- package/dist/core/recurrence/kinds/one-off.js.map +1 -0
- package/dist/core/recurrence/kinds/recurring-cron.d.ts +7 -0
- package/dist/core/recurrence/kinds/recurring-cron.js +64 -0
- package/dist/core/recurrence/kinds/recurring-cron.js.map +1 -0
- package/dist/core/recurrence/next-run.d.ts +2 -0
- package/dist/core/recurrence/next-run.js +37 -24
- package/dist/core/recurrence/next-run.js.map +1 -1
- package/dist/core/recurrence/periods.d.ts +2 -0
- package/dist/core/recurrence/periods.js +30 -0
- package/dist/core/recurrence/periods.js.map +1 -0
- package/dist/core/recurrence/resolve.d.ts +2 -0
- package/dist/core/recurrence/resolve.js +25 -0
- package/dist/core/recurrence/resolve.js.map +1 -0
- package/dist/core/recurrence/validate.js +9 -38
- package/dist/core/recurrence/validate.js.map +1 -1
- package/dist/core/retention/prune.d.ts +1 -1
- package/dist/core/retention/prune.js +11 -9
- package/dist/core/retention/prune.js.map +1 -1
- package/dist/core/retention/store.d.ts +1 -1
- package/dist/core/scheduler.d.ts +16 -0
- package/dist/core/scheduler.js +3 -0
- package/dist/core/scheduler.js.map +1 -0
- package/dist/core/types/schedule.d.ts +17 -4
- package/dist/core/types/task.d.ts +2 -5
- package/dist/observability/attributes.d.ts +41 -0
- package/dist/observability/attributes.js +56 -0
- package/dist/observability/attributes.js.map +1 -0
- package/dist/observability/executor-tracing.d.ts +4 -0
- package/dist/observability/executor-tracing.js +61 -0
- package/dist/observability/executor-tracing.js.map +1 -0
- package/dist/observability/materializer-tracing.d.ts +3 -0
- package/dist/observability/materializer-tracing.js +22 -0
- package/dist/observability/materializer-tracing.js.map +1 -0
- package/dist/observability/metrics.d.ts +11 -0
- package/dist/observability/metrics.js +14 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/pass-tracing.d.ts +2 -0
- package/dist/observability/pass-tracing.js +24 -0
- package/dist/observability/pass-tracing.js.map +1 -0
- package/dist/observability/provisioner-tracing.d.ts +11 -0
- package/dist/observability/provisioner-tracing.js +51 -0
- package/dist/observability/provisioner-tracing.js.map +1 -0
- package/dist/observability/tracer.d.ts +21 -0
- package/dist/observability/tracer.js +10 -0
- package/dist/observability/tracer.js.map +1 -0
- package/package.json +11 -22
- package/dist/core/enums.d.ts +0 -1
- package/dist/core/enums.js +0 -10
- package/dist/core/enums.js.map +0 -1
- package/dist/executor/backoff.js.map +0 -1
- package/dist/executor/executor.d.ts +0 -23
- package/dist/executor/executor.js +0 -133
- package/dist/executor/executor.js.map +0 -1
- package/dist/executor/precision-timer.js.map +0 -1
- package/dist/executor/task-handler.js.map +0 -1
- package/dist/reaper/reaper.js +0 -37
- package/dist/reaper/reaper.js.map +0 -1
- package/dist/storage/index.d.ts +0 -3
- package/dist/storage/index.js +0 -12
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/mappers.d.ts +0 -6
- package/dist/storage/mappers.js +0 -72
- package/dist/storage/mappers.js.map +0 -1
- package/dist/storage/materializer-store.d.ts +0 -14
- package/dist/storage/materializer-store.js +0 -83
- package/dist/storage/materializer-store.js.map +0 -1
- package/dist/storage/scheduler.service.d.ts +0 -16
- package/dist/storage/scheduler.service.js +0 -70
- package/dist/storage/scheduler.service.js.map +0 -1
- /package/dist/{executor → core/executor}/backoff.d.ts +0 -0
- /package/dist/{executor → core/executor}/backoff.js +0 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateCron = validateCron;
|
|
4
|
+
exports.resolvedTimezone = resolvedTimezone;
|
|
5
|
+
exports.parseCron = parseCron;
|
|
6
|
+
exports.cronNextRun = cronNextRun;
|
|
7
|
+
exports.cronOccurrences = cronOccurrences;
|
|
8
|
+
exports.resolveCron = resolveCron;
|
|
9
|
+
const cron_parser_1 = require("cron-parser");
|
|
10
|
+
const luxon_1 = require("luxon");
|
|
11
|
+
const errors_1 = require("../../errors");
|
|
12
|
+
const field_1 = require("../field");
|
|
13
|
+
const CRON_FIELD_COUNT = 6;
|
|
14
|
+
function validateCron(schedule) {
|
|
15
|
+
const expression = schedule.cronExpression;
|
|
16
|
+
if (typeof expression !== 'string') {
|
|
17
|
+
throw new errors_1.InvalidScheduleError(`${schedule.kind}.cronExpression must be a string, got ${JSON.stringify(expression)}`);
|
|
18
|
+
}
|
|
19
|
+
const fieldCount = expression.trim().split(/\s+/).length;
|
|
20
|
+
if (fieldCount !== CRON_FIELD_COUNT) {
|
|
21
|
+
throw new errors_1.InvalidScheduleError(`Cron expression must have ${CRON_FIELD_COUNT} fields (seconds included), got ${fieldCount}: ${JSON.stringify(expression)}`);
|
|
22
|
+
}
|
|
23
|
+
if (schedule.timezone !== null && !luxon_1.IANAZone.isValidZone(schedule.timezone)) {
|
|
24
|
+
throw new errors_1.InvalidScheduleError(`Unknown IANA timezone: ${JSON.stringify(schedule.timezone)}`);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
cron_parser_1.CronExpressionParser.parse(expression, { tz: schedule.timezone ?? 'UTC' });
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
throw new errors_1.InvalidScheduleError(`Invalid cron expression ${JSON.stringify(expression)}: ${error.message}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function resolvedTimezone(schedule) {
|
|
34
|
+
if (schedule.timezone === null) {
|
|
35
|
+
throw new errors_1.InvalidScheduleError('Cron timezone must be resolved to a concrete zone before computing the next run, got null');
|
|
36
|
+
}
|
|
37
|
+
return schedule.timezone;
|
|
38
|
+
}
|
|
39
|
+
function parseCron(cronExpression, after, timezone) {
|
|
40
|
+
try {
|
|
41
|
+
return cron_parser_1.CronExpressionParser.parse(cronExpression, { currentDate: after, tz: timezone });
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw new errors_1.InvalidScheduleError(`Failed to evaluate cron expression ${JSON.stringify(cronExpression)} in timezone ${JSON.stringify(timezone)}: ${error.message}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function cronNextRun(schedule, after) {
|
|
48
|
+
return parseCron(schedule.cronExpression, after, resolvedTimezone(schedule)).next().toDate();
|
|
49
|
+
}
|
|
50
|
+
function* cronOccurrences(schedule, first) {
|
|
51
|
+
const cursor = parseCron(schedule.cronExpression, first, resolvedTimezone(schedule));
|
|
52
|
+
yield first;
|
|
53
|
+
for (;;) {
|
|
54
|
+
yield cursor.next().toDate();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function resolveCron(job, defaultTimezone) {
|
|
58
|
+
return {
|
|
59
|
+
kind: 'cron',
|
|
60
|
+
cronExpression: (0, field_1.required)(job, 'cronExpression'),
|
|
61
|
+
timezone: job.timezone ?? defaultTimezone,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../../../../src/core/recurrence/kinds/cron.ts"],"names":[],"mappings":";;AAmBA,oCA4BC;AASD,4CAOC;AAaD,8BAYC;AASD,kCAEC;AAOD,0CAMC;AASD,kCAOC;AAhID,6CAAmD;AACnD,iCAAiC;AAGjC,yCAAoD;AAEpD,oCAAoC;AAGpC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAU3B,SAAgB,YAAY,CAAC,QAA8C;IAE1E,MAAM,UAAU,GAAY,QAAQ,CAAC,cAAc,CAAC;IACpD,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,6BAAoB,CAC7B,GAAG,QAAQ,CAAC,IAAI,yCAAyC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CACrF,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IACzD,IAAI,UAAU,KAAK,gBAAgB,EAAE,CAAC;QACrC,MAAM,IAAI,6BAAoB,CAC7B,6BAA6B,gBAAgB,mCAAmC,UAAU,KAAK,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAC3H,CAAC;IACH,CAAC;IAGD,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,gBAAQ,CAAC,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5E,MAAM,IAAI,6BAAoB,CAAC,0BAA0B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,CAAC;QACJ,kCAAoB,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,IAAI,KAAK,EAAE,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,6BAAoB,CAC7B,2BAA2B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAM,KAAe,CAAC,OAAO,EAAE,CACpF,CAAC;IACH,CAAC;AACF,CAAC;AASD,SAAgB,gBAAgB,CAAC,QAA8C;IAC9E,IAAI,QAAQ,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;QAChC,MAAM,IAAI,6BAAoB,CAC7B,2FAA2F,CAC3F,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC,QAAQ,CAAC;AAC1B,CAAC;AAaD,SAAgB,SAAS,CACxB,cAA8B,EAC9B,KAAW,EACX,QAAgB;IAEhB,IAAI,CAAC;QACJ,OAAO,kCAAoB,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IACzF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,6BAAoB,CAC7B,sCAAsC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,gBAAgB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAM,KAAe,CAAC,OAAO,EAAE,CAC3I,CAAC;IACH,CAAC;AACF,CAAC;AASD,SAAgB,WAAW,CAAC,QAA8C,EAAE,KAAW;IACtF,OAAO,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,KAAK,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;AAC9F,CAAC;AAOD,QAAe,CAAC,CAAC,eAAe,CAAC,QAAsB,EAAE,KAAW;IACnE,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,cAAc,EAAE,KAAK,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrF,MAAM,KAAK,CAAC;IACZ,SAAS,CAAC;QACT,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;IAC9B,CAAC;AACF,CAAC;AASD,SAAgB,WAAW,CAAC,GAAiB,EAAE,eAAuB;IACrE,OAAO;QACN,IAAI,EAAE,MAAM;QAEZ,cAAc,EAAE,IAAA,gBAAQ,EAAC,GAAG,EAAE,gBAAgB,CAAmB;QACjE,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,eAAe;KACzC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { IntervalSchedule, ScheduledJob } from '../../types';
|
|
2
|
+
export declare function validateInterval(schedule: IntervalSchedule): void;
|
|
3
|
+
export declare function intervalNextRun(schedule: IntervalSchedule, after: Date): Date;
|
|
4
|
+
export declare function intervalOccurrences(schedule: IntervalSchedule, first: Date): Generator<Date>;
|
|
5
|
+
export declare function resolveInterval(job: ScheduledJob): IntervalSchedule;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateInterval = validateInterval;
|
|
4
|
+
exports.intervalNextRun = intervalNextRun;
|
|
5
|
+
exports.intervalOccurrences = intervalOccurrences;
|
|
6
|
+
exports.resolveInterval = resolveInterval;
|
|
7
|
+
const constants_1 = require("@n8n/constants");
|
|
8
|
+
const errors_1 = require("../../errors");
|
|
9
|
+
const field_1 = require("../field");
|
|
10
|
+
function validateInterval(schedule) {
|
|
11
|
+
if (!Number.isInteger(schedule.intervalSeconds) || schedule.intervalSeconds <= 0) {
|
|
12
|
+
throw new errors_1.InvalidScheduleError(`interval.intervalSeconds must be a positive integer, got ${JSON.stringify(schedule.intervalSeconds)}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function intervalNextRun(schedule, after) {
|
|
16
|
+
return new Date(after.getTime() + schedule.intervalSeconds * constants_1.Time.seconds.toMilliseconds);
|
|
17
|
+
}
|
|
18
|
+
function* intervalOccurrences(schedule, first) {
|
|
19
|
+
let previous = first;
|
|
20
|
+
yield previous;
|
|
21
|
+
for (;;) {
|
|
22
|
+
previous = intervalNextRun(schedule, previous);
|
|
23
|
+
yield previous;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function resolveInterval(job) {
|
|
27
|
+
return { kind: 'interval', intervalSeconds: (0, field_1.required)(job, 'intervalSeconds') };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=interval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interval.js","sourceRoot":"","sources":["../../../../src/core/recurrence/kinds/interval.ts"],"names":[],"mappings":";;AAWA,4CAMC;AASD,0CAEC;AAOD,kDAOC;AAQD,0CAEC;AApDD,8CAAsC;AAEtC,yCAAoD;AAEpD,oCAAoC;AAOpC,SAAgB,gBAAgB,CAAC,QAA0B;IAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,QAAQ,CAAC,eAAe,IAAI,CAAC,EAAE,CAAC;QAClF,MAAM,IAAI,6BAAoB,CAC7B,4DAA4D,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CACtG,CAAC;IACH,CAAC;AACF,CAAC;AASD,SAAgB,eAAe,CAAC,QAA0B,EAAE,KAAW;IACtE,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,eAAe,GAAG,gBAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;AAC3F,CAAC;AAOD,QAAe,CAAC,CAAC,mBAAmB,CAAC,QAA0B,EAAE,KAAW;IAC3E,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,QAAQ,CAAC;IACf,SAAS,CAAC;QACT,QAAQ,GAAG,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/C,MAAM,QAAQ,CAAC;IAChB,CAAC;AACF,CAAC;AAQD,SAAgB,eAAe,CAAC,GAAiB;IAChD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,eAAe,EAAE,IAAA,gBAAQ,EAAC,GAAG,EAAE,iBAAiB,CAAC,EAAE,CAAC;AAChF,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { OneOffSchedule, ScheduledJob } from '../../types';
|
|
2
|
+
export declare function validateOneOff(schedule: OneOffSchedule): void;
|
|
3
|
+
export declare function oneOffNextRun(schedule: OneOffSchedule, after: Date): Date | null;
|
|
4
|
+
export declare function oneOffOccurrences(first: Date): Generator<Date>;
|
|
5
|
+
export declare function resolveOneOff(job: ScheduledJob): OneOffSchedule;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateOneOff = validateOneOff;
|
|
4
|
+
exports.oneOffNextRun = oneOffNextRun;
|
|
5
|
+
exports.oneOffOccurrences = oneOffOccurrences;
|
|
6
|
+
exports.resolveOneOff = resolveOneOff;
|
|
7
|
+
const errors_1 = require("../../errors");
|
|
8
|
+
const field_1 = require("../field");
|
|
9
|
+
function validateOneOff(schedule) {
|
|
10
|
+
const fireAt = schedule.fireAt;
|
|
11
|
+
if (!(fireAt instanceof Date) || Number.isNaN(fireAt.getTime())) {
|
|
12
|
+
throw new errors_1.InvalidScheduleError('one_off.fireAt must be a valid Date');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function oneOffNextRun(schedule, after) {
|
|
16
|
+
return after.getTime() < schedule.fireAt.getTime() ? schedule.fireAt : null;
|
|
17
|
+
}
|
|
18
|
+
function* oneOffOccurrences(first) {
|
|
19
|
+
yield first;
|
|
20
|
+
}
|
|
21
|
+
function resolveOneOff(job) {
|
|
22
|
+
return { kind: 'one_off', fireAt: (0, field_1.required)(job, 'fireAt') };
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=one-off.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"one-off.js","sourceRoot":"","sources":["../../../../src/core/recurrence/kinds/one-off.ts"],"names":[],"mappings":";;AASA,wCAKC;AAQD,sCAEC;AAOD,8CAEC;AAQD,sCAEC;AA3CD,yCAAoD;AAEpD,oCAAoC;AAOpC,SAAgB,cAAc,CAAC,QAAwB;IACtD,MAAM,MAAM,GAAY,QAAQ,CAAC,MAAM,CAAC;IACxC,IAAI,CAAC,CAAC,MAAM,YAAY,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QACjE,MAAM,IAAI,6BAAoB,CAAC,qCAAqC,CAAC,CAAC;IACvE,CAAC;AACF,CAAC;AAQD,SAAgB,aAAa,CAAC,QAAwB,EAAE,KAAW;IAClE,OAAO,KAAK,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7E,CAAC;AAOD,QAAe,CAAC,CAAC,iBAAiB,CAAC,KAAW;IAC7C,MAAM,KAAK,CAAC;AACb,CAAC;AAQD,SAAgB,aAAa,CAAC,GAAiB;IAC9C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,IAAA,gBAAQ,EAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC;AAC7D,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RecurringCronSchedule, ScheduledJob } from '../../types';
|
|
2
|
+
export declare function validateRecurringCron(schedule: RecurringCronSchedule): void;
|
|
3
|
+
export declare function isOnCadence(previousFire: Date, candidate: Date, schedule: RecurringCronSchedule, timezone: string): boolean;
|
|
4
|
+
export declare function recurringCronNextRun(schedule: RecurringCronSchedule, after: Date): Date;
|
|
5
|
+
export declare function recurringCronFirstRun(schedule: RecurringCronSchedule, from: Date): Date;
|
|
6
|
+
export declare function recurringCronOccurrences(schedule: RecurringCronSchedule, first: Date): Generator<Date>;
|
|
7
|
+
export declare function resolveRecurringCron(job: ScheduledJob, defaultTimezone: string): RecurringCronSchedule;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateRecurringCron = validateRecurringCron;
|
|
4
|
+
exports.isOnCadence = isOnCadence;
|
|
5
|
+
exports.recurringCronNextRun = recurringCronNextRun;
|
|
6
|
+
exports.recurringCronFirstRun = recurringCronFirstRun;
|
|
7
|
+
exports.recurringCronOccurrences = recurringCronOccurrences;
|
|
8
|
+
exports.resolveRecurringCron = resolveRecurringCron;
|
|
9
|
+
const constants_1 = require("@n8n/constants");
|
|
10
|
+
const errors_1 = require("../../errors");
|
|
11
|
+
const field_1 = require("../field");
|
|
12
|
+
const periods_1 = require("../periods");
|
|
13
|
+
const cron_1 = require("./cron");
|
|
14
|
+
const MAX_RECURRENCE_CANDIDATES = 10_000;
|
|
15
|
+
function validateRecurringCron(schedule) {
|
|
16
|
+
(0, cron_1.validateCron)(schedule);
|
|
17
|
+
if (!constants_1.RecurringCronUnitList.includes(schedule.recurrenceUnit)) {
|
|
18
|
+
throw new errors_1.InvalidScheduleError(`recurring_cron.recurrenceUnit must be one of ${constants_1.RecurringCronUnitList.join(', ')}, got ${JSON.stringify(schedule.recurrenceUnit)}`);
|
|
19
|
+
}
|
|
20
|
+
if (!Number.isInteger(schedule.recurrenceSize) || schedule.recurrenceSize < 2) {
|
|
21
|
+
throw new errors_1.InvalidScheduleError(`recurring_cron.recurrenceSize must be an integer of at least 2 (a stride of 1 is a plain cron), got ${JSON.stringify(schedule.recurrenceSize)}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function isOnCadence(previousFire, candidate, schedule, timezone) {
|
|
25
|
+
const elapsed = (0, periods_1.periodsBetween)(previousFire, candidate, schedule.recurrenceUnit, timezone);
|
|
26
|
+
return elapsed === 0 || elapsed >= schedule.recurrenceSize;
|
|
27
|
+
}
|
|
28
|
+
function advanceToOnCadence(cursor, schedule, previousFire, timezone) {
|
|
29
|
+
for (let scanned = 0; scanned < MAX_RECURRENCE_CANDIDATES; scanned++) {
|
|
30
|
+
const candidate = cursor.next().toDate();
|
|
31
|
+
if (isOnCadence(previousFire, candidate, schedule, timezone)) {
|
|
32
|
+
return candidate;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
throw new errors_1.InvalidScheduleError(`No fire of cron expression ${JSON.stringify(schedule.cronExpression)} lands on the every-${schedule.recurrenceSize}-${schedule.recurrenceUnit} cadence within ${MAX_RECURRENCE_CANDIDATES} candidates`);
|
|
36
|
+
}
|
|
37
|
+
function recurringCronNextRun(schedule, after) {
|
|
38
|
+
const timezone = (0, cron_1.resolvedTimezone)(schedule);
|
|
39
|
+
const cursor = (0, cron_1.parseCron)(schedule.cronExpression, after, timezone);
|
|
40
|
+
return advanceToOnCadence(cursor, schedule, after, timezone);
|
|
41
|
+
}
|
|
42
|
+
function recurringCronFirstRun(schedule, from) {
|
|
43
|
+
return (0, cron_1.cronNextRun)(schedule, from);
|
|
44
|
+
}
|
|
45
|
+
function* recurringCronOccurrences(schedule, first) {
|
|
46
|
+
const timezone = (0, cron_1.resolvedTimezone)(schedule);
|
|
47
|
+
const cursor = (0, cron_1.parseCron)(schedule.cronExpression, first, timezone);
|
|
48
|
+
let previous = first;
|
|
49
|
+
yield previous;
|
|
50
|
+
for (;;) {
|
|
51
|
+
previous = advanceToOnCadence(cursor, schedule, previous, timezone);
|
|
52
|
+
yield previous;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function resolveRecurringCron(job, defaultTimezone) {
|
|
56
|
+
return {
|
|
57
|
+
kind: 'recurring_cron',
|
|
58
|
+
cronExpression: (0, field_1.required)(job, 'cronExpression'),
|
|
59
|
+
timezone: job.timezone ?? defaultTimezone,
|
|
60
|
+
recurrenceUnit: (0, field_1.required)(job, 'recurrenceUnit'),
|
|
61
|
+
recurrenceSize: (0, field_1.required)(job, 'recurrenceSize'),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=recurring-cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recurring-cron.js","sourceRoot":"","sources":["../../../../src/core/recurrence/kinds/recurring-cron.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import type { Schedule } from '../types';
|
|
2
2
|
export declare function computeNextRunAt(schedule: Schedule, after: Date): Date | null;
|
|
3
|
+
export declare function computeFirstRunAt(schedule: Schedule, from: Date): Date | null;
|
|
4
|
+
export declare function occurrencesFrom(schedule: Schedule, first: Date): Generator<Date>;
|
|
@@ -1,40 +1,53 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.computeNextRunAt = computeNextRunAt;
|
|
4
|
-
|
|
4
|
+
exports.computeFirstRunAt = computeFirstRunAt;
|
|
5
|
+
exports.occurrencesFrom = occurrencesFrom;
|
|
5
6
|
const errors_1 = require("../errors");
|
|
7
|
+
const cron_1 = require("./kinds/cron");
|
|
8
|
+
const interval_1 = require("./kinds/interval");
|
|
9
|
+
const one_off_1 = require("./kinds/one-off");
|
|
10
|
+
const recurring_cron_1 = require("./kinds/recurring-cron");
|
|
6
11
|
const validate_1 = require("./validate");
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
function computeNextRunAt(schedule, after) {
|
|
13
|
+
(0, validate_1.validateSchedule)(schedule);
|
|
14
|
+
switch (schedule.kind) {
|
|
15
|
+
case 'cron':
|
|
16
|
+
return (0, cron_1.cronNextRun)(schedule, after);
|
|
17
|
+
case 'recurring_cron':
|
|
18
|
+
return (0, recurring_cron_1.recurringCronNextRun)(schedule, after);
|
|
19
|
+
case 'interval':
|
|
20
|
+
return (0, interval_1.intervalNextRun)(schedule, after);
|
|
21
|
+
case 'one_off':
|
|
22
|
+
return (0, one_off_1.oneOffNextRun)(schedule, after);
|
|
23
|
+
default: {
|
|
24
|
+
const exhaustive = schedule;
|
|
25
|
+
throw new errors_1.InvalidScheduleError(`Unknown schedule kind: ${JSON.stringify(exhaustive.kind)}`);
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
28
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
function computeFirstRunAt(schedule, from) {
|
|
30
|
+
if (schedule.kind === 'recurring_cron') {
|
|
31
|
+
(0, validate_1.validateSchedule)(schedule);
|
|
32
|
+
return (0, recurring_cron_1.recurringCronFirstRun)(schedule, from);
|
|
33
|
+
}
|
|
34
|
+
return computeNextRunAt(schedule, from);
|
|
25
35
|
}
|
|
26
|
-
function
|
|
36
|
+
function* occurrencesFrom(schedule, first) {
|
|
27
37
|
(0, validate_1.validateSchedule)(schedule);
|
|
28
38
|
switch (schedule.kind) {
|
|
29
39
|
case 'cron':
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
40
|
+
yield* (0, cron_1.cronOccurrences)(schedule, first);
|
|
41
|
+
return;
|
|
42
|
+
case 'recurring_cron':
|
|
43
|
+
yield* (0, recurring_cron_1.recurringCronOccurrences)(schedule, first);
|
|
44
|
+
return;
|
|
34
45
|
case 'interval':
|
|
35
|
-
|
|
46
|
+
yield* (0, interval_1.intervalOccurrences)(schedule, first);
|
|
47
|
+
return;
|
|
36
48
|
case 'one_off':
|
|
37
|
-
|
|
49
|
+
yield* (0, one_off_1.oneOffOccurrences)(first);
|
|
50
|
+
return;
|
|
38
51
|
default: {
|
|
39
52
|
const exhaustive = schedule;
|
|
40
53
|
throw new errors_1.InvalidScheduleError(`Unknown schedule kind: ${JSON.stringify(exhaustive.kind)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"next-run.js","sourceRoot":"","sources":["../../../src/core/recurrence/next-run.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"next-run.js","sourceRoot":"","sources":["../../../src/core/recurrence/next-run.ts"],"names":[],"mappings":";;AAgCA,4CAuBC;AAYD,8CAMC;AAkBD,0CAuBC;AAlHD,sCAAiD;AAEjD,uCAA4D;AAC5D,+CAAwE;AACxE,6CAAmE;AACnE,2DAIgC;AAChC,yCAA8C;AAsB9C,SAAgB,gBAAgB,CAAC,QAAkB,EAAE,KAAW;IAC/D,IAAA,2BAAgB,EAAC,QAAQ,CAAC,CAAC;IAE3B,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM;YACV,OAAO,IAAA,kBAAW,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACrC,KAAK,gBAAgB;YACpB,OAAO,IAAA,qCAAoB,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC9C,KAAK,UAAU;YACd,OAAO,IAAA,0BAAe,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACzC,KAAK,SAAS;YACb,OAAO,IAAA,uBAAa,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAIvC,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,UAAU,GAAU,QAAQ,CAAC;YACnC,MAAM,IAAI,6BAAoB,CAC7B,0BAA0B,IAAI,CAAC,SAAS,CAAE,UAAuB,CAAC,IAAI,CAAC,EAAE,CACzE,CAAC;QACH,CAAC;IAEF,CAAC;AACF,CAAC;AAYD,SAAgB,iBAAiB,CAAC,QAAkB,EAAE,IAAU;IAC/D,IAAI,QAAQ,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;QACxC,IAAA,2BAAgB,EAAC,QAAQ,CAAC,CAAC;QAC3B,OAAO,IAAA,sCAAqB,EAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAkBD,QAAe,CAAC,CAAC,eAAe,CAAC,QAAkB,EAAE,KAAW;IAC/D,IAAA,2BAAgB,EAAC,QAAQ,CAAC,CAAC;IAE3B,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM;YACV,KAAK,CAAC,CAAC,IAAA,sBAAe,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACxC,OAAO;QACR,KAAK,gBAAgB;YACpB,KAAK,CAAC,CAAC,IAAA,yCAAwB,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACjD,OAAO;QACR,KAAK,UAAU;YACd,KAAK,CAAC,CAAC,IAAA,8BAAmB,EAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC5C,OAAO;QACR,KAAK,SAAS;YACb,KAAK,CAAC,CAAC,IAAA,2BAAiB,EAAC,KAAK,CAAC,CAAC;YAChC,OAAO;QACR,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,UAAU,GAAU,QAAQ,CAAC;YACnC,MAAM,IAAI,6BAAoB,CAC7B,0BAA0B,IAAI,CAAC,SAAS,CAAE,UAAuB,CAAC,IAAI,CAAC,EAAE,CACzE,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.periodsBetween = periodsBetween;
|
|
4
|
+
const constants_1 = require("@n8n/constants");
|
|
5
|
+
const luxon_1 = require("luxon");
|
|
6
|
+
function periodsBetween(from, to, unit, timezone) {
|
|
7
|
+
const start = luxon_1.DateTime.fromJSDate(from, { zone: timezone });
|
|
8
|
+
const end = luxon_1.DateTime.fromJSDate(to, { zone: timezone });
|
|
9
|
+
switch (unit) {
|
|
10
|
+
case constants_1.RecurringCronUnit.Hours:
|
|
11
|
+
return (calendarDaysBetween(start.startOf('day'), end.startOf('day')) * 24 + end.hour - start.hour);
|
|
12
|
+
case constants_1.RecurringCronUnit.Days:
|
|
13
|
+
return calendarDaysBetween(start.startOf('day'), end.startOf('day'));
|
|
14
|
+
case constants_1.RecurringCronUnit.Weeks:
|
|
15
|
+
return calendarDaysBetween(startOfSundayWeek(start), startOfSundayWeek(end)) / 7;
|
|
16
|
+
case constants_1.RecurringCronUnit.Months:
|
|
17
|
+
return end.year * 12 + end.month - (start.year * 12 + start.month);
|
|
18
|
+
default: {
|
|
19
|
+
const exhaustive = unit;
|
|
20
|
+
return exhaustive;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function calendarDaysBetween(startOfFromDay, startOfToDay) {
|
|
25
|
+
return Math.round(startOfToDay.diff(startOfFromDay, 'days').days);
|
|
26
|
+
}
|
|
27
|
+
function startOfSundayWeek(instant) {
|
|
28
|
+
return instant.startOf('day').minus({ days: instant.weekday % 7 });
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=periods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"periods.js","sourceRoot":"","sources":["../../../src/core/recurrence/periods.ts"],"names":[],"mappings":";;AAmBA,wCAyBC;AA5CD,8CAAmD;AACnD,iCAAiC;AAkBjC,SAAgB,cAAc,CAC7B,IAAU,EACV,EAAQ,EACR,IAAuB,EACvB,QAAgB;IAEhB,MAAM,KAAK,GAAG,gBAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5D,MAAM,GAAG,GAAG,gBAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAExD,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,6BAAiB,CAAC,KAAK;YAC3B,OAAO,CACN,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,GAAG,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAC1F,CAAC;QACH,KAAK,6BAAiB,CAAC,IAAI;YAC1B,OAAO,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,KAAK,6BAAiB,CAAC,KAAK;YAC3B,OAAO,mBAAmB,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAClF,KAAK,6BAAiB,CAAC,MAAM;YAC5B,OAAO,GAAG,CAAC,IAAI,GAAG,EAAE,GAAG,GAAG,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QACpE,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,UAAU,GAAU,IAAI,CAAC;YAC/B,OAAO,UAAU,CAAC;QACnB,CAAC;IACF,CAAC;AACF,CAAC;AAUD,SAAS,mBAAmB,CAAC,cAAwB,EAAE,YAAsB;IAC5E,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC;AACnE,CAAC;AAOD,SAAS,iBAAiB,CAAC,OAAiB;IAE3C,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveSchedule = resolveSchedule;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
const cron_1 = require("./kinds/cron");
|
|
6
|
+
const interval_1 = require("./kinds/interval");
|
|
7
|
+
const one_off_1 = require("./kinds/one-off");
|
|
8
|
+
const recurring_cron_1 = require("./kinds/recurring-cron");
|
|
9
|
+
function resolveSchedule(job, defaultTimezone) {
|
|
10
|
+
switch (job.kind) {
|
|
11
|
+
case 'cron':
|
|
12
|
+
return (0, cron_1.resolveCron)(job, defaultTimezone);
|
|
13
|
+
case 'recurring_cron':
|
|
14
|
+
return (0, recurring_cron_1.resolveRecurringCron)(job, defaultTimezone);
|
|
15
|
+
case 'interval':
|
|
16
|
+
return (0, interval_1.resolveInterval)(job);
|
|
17
|
+
case 'one_off':
|
|
18
|
+
return (0, one_off_1.resolveOneOff)(job);
|
|
19
|
+
default: {
|
|
20
|
+
const exhaustive = job.kind;
|
|
21
|
+
throw new errors_1.CorruptStorageRowError(`scheduled_job ${job.id} has unknown kind '${String(exhaustive)}'`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/core/recurrence/resolve.ts"],"names":[],"mappings":";;AAoBA,0CAiBC;AArCD,sCAAmD;AAEnD,uCAA2C;AAC3C,+CAAmD;AACnD,6CAAgD;AAChD,2DAA8D;AAe9D,SAAgB,eAAe,CAAC,GAAiB,EAAE,eAAuB;IACzE,QAAQ,GAAG,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,MAAM;YACV,OAAO,IAAA,kBAAW,EAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QAC1C,KAAK,gBAAgB;YACpB,OAAO,IAAA,qCAAoB,EAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACnD,KAAK,UAAU;YACd,OAAO,IAAA,0BAAe,EAAC,GAAG,CAAC,CAAC;QAC7B,KAAK,SAAS;YACb,OAAO,IAAA,uBAAa,EAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,UAAU,GAAU,GAAG,CAAC,IAAI,CAAC;YACnC,MAAM,IAAI,+BAAsB,CAC/B,iBAAiB,GAAG,CAAC,EAAE,sBAAsB,MAAM,CAAC,UAAU,CAAC,GAAG,CAClE,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC"}
|
|
@@ -1,50 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateSchedule = validateSchedule;
|
|
4
|
-
const cron_parser_1 = require("cron-parser");
|
|
5
|
-
const luxon_1 = require("luxon");
|
|
6
4
|
const errors_1 = require("../errors");
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
throw new errors_1.InvalidScheduleError(`cron.cronExpression must be a string, got ${JSON.stringify(expression)}`);
|
|
12
|
-
}
|
|
13
|
-
const fieldCount = expression.trim().split(/\s+/).length;
|
|
14
|
-
if (fieldCount !== CRON_FIELD_COUNT) {
|
|
15
|
-
throw new errors_1.InvalidScheduleError(`Cron expression must have ${CRON_FIELD_COUNT} fields (seconds included), got ${fieldCount}: ${JSON.stringify(expression)}`);
|
|
16
|
-
}
|
|
17
|
-
if (schedule.timezone !== null && !luxon_1.IANAZone.isValidZone(schedule.timezone)) {
|
|
18
|
-
throw new errors_1.InvalidScheduleError(`Unknown IANA timezone: ${JSON.stringify(schedule.timezone)}`);
|
|
19
|
-
}
|
|
20
|
-
try {
|
|
21
|
-
cron_parser_1.CronExpressionParser.parse(expression, {
|
|
22
|
-
tz: schedule.timezone ?? 'UTC',
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
catch (error) {
|
|
26
|
-
throw new errors_1.InvalidScheduleError(`Invalid cron expression ${JSON.stringify(expression)}: ${error.message}`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function validateInterval(schedule) {
|
|
30
|
-
if (!Number.isInteger(schedule.intervalSeconds) || schedule.intervalSeconds <= 0) {
|
|
31
|
-
throw new errors_1.InvalidScheduleError(`interval.intervalSeconds must be a positive integer, got ${JSON.stringify(schedule.intervalSeconds)}`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function validateOneOff(schedule) {
|
|
35
|
-
const fireAt = schedule.fireAt;
|
|
36
|
-
if (!(fireAt instanceof Date) || Number.isNaN(fireAt.getTime())) {
|
|
37
|
-
throw new errors_1.InvalidScheduleError('one_off.fireAt must be a valid Date');
|
|
38
|
-
}
|
|
39
|
-
}
|
|
5
|
+
const cron_1 = require("./kinds/cron");
|
|
6
|
+
const interval_1 = require("./kinds/interval");
|
|
7
|
+
const one_off_1 = require("./kinds/one-off");
|
|
8
|
+
const recurring_cron_1 = require("./kinds/recurring-cron");
|
|
40
9
|
function validateSchedule(schedule) {
|
|
41
10
|
switch (schedule.kind) {
|
|
42
11
|
case 'cron':
|
|
43
|
-
return validateCron(schedule);
|
|
12
|
+
return (0, cron_1.validateCron)(schedule);
|
|
13
|
+
case 'recurring_cron':
|
|
14
|
+
return (0, recurring_cron_1.validateRecurringCron)(schedule);
|
|
44
15
|
case 'interval':
|
|
45
|
-
return validateInterval(schedule);
|
|
16
|
+
return (0, interval_1.validateInterval)(schedule);
|
|
46
17
|
case 'one_off':
|
|
47
|
-
return validateOneOff(schedule);
|
|
18
|
+
return (0, one_off_1.validateOneOff)(schedule);
|
|
48
19
|
default: {
|
|
49
20
|
const exhaustive = schedule;
|
|
50
21
|
throw new errors_1.InvalidScheduleError(`Unknown schedule kind: ${JSON.stringify(exhaustive.kind)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/core/recurrence/validate.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../../src/core/recurrence/validate.ts"],"names":[],"mappings":";;AAaA,4CAiBC;AA9BD,sCAAiD;AAEjD,uCAA4C;AAC5C,+CAAoD;AACpD,6CAAiD;AACjD,2DAA+D;AAQ/D,SAAgB,gBAAgB,CAAC,QAAkB;IAClD,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvB,KAAK,MAAM;YACV,OAAO,IAAA,mBAAY,EAAC,QAAQ,CAAC,CAAC;QAC/B,KAAK,gBAAgB;YACpB,OAAO,IAAA,sCAAqB,EAAC,QAAQ,CAAC,CAAC;QACxC,KAAK,UAAU;YACd,OAAO,IAAA,2BAAgB,EAAC,QAAQ,CAAC,CAAC;QACnC,KAAK,SAAS;YACb,OAAO,IAAA,wBAAc,EAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,CAAC,CAAC,CAAC;YACT,MAAM,UAAU,GAAU,QAAQ,CAAC;YACnC,MAAM,IAAI,6BAAoB,CAC7B,0BAA0B,IAAI,CAAC,SAAS,CAAE,UAAuB,CAAC,IAAI,CAAC,EAAE,CACzE,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC"}
|
|
@@ -4,4 +4,4 @@ export interface RetentionSummary {
|
|
|
4
4
|
deleted: number;
|
|
5
5
|
drained: boolean;
|
|
6
6
|
}
|
|
7
|
-
export declare function prune(store: RetentionStore, options?: RetentionOptions): Promise<RetentionSummary>;
|
|
7
|
+
export declare function prune(store: RetentionStore, options?: RetentionOptions, signal?: AbortSignal): Promise<RetentionSummary>;
|
|
@@ -2,22 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.prune = prune;
|
|
4
4
|
const constants_1 = require("@n8n/constants");
|
|
5
|
-
const enums_1 = require("../enums");
|
|
6
5
|
const errors_1 = require("../errors");
|
|
7
6
|
const options_1 = require("./options");
|
|
8
7
|
function retentionWindows(options) {
|
|
9
8
|
return [
|
|
10
9
|
{
|
|
11
|
-
statuses: [
|
|
10
|
+
statuses: [constants_1.ScheduledTaskStatus.Succeeded, constants_1.ScheduledTaskStatus.Cancelled],
|
|
12
11
|
olderThanSeconds: options.retentionSeconds,
|
|
13
12
|
},
|
|
14
13
|
{
|
|
15
|
-
statuses: [
|
|
14
|
+
statuses: [constants_1.ScheduledTaskStatus.Failed, constants_1.ScheduledTaskStatus.Missed],
|
|
16
15
|
olderThanSeconds: options.failedRetentionSeconds,
|
|
17
16
|
},
|
|
18
17
|
];
|
|
19
18
|
}
|
|
20
|
-
async function prune(store, options = options_1.DEFAULT_RETENTION_OPTIONS) {
|
|
19
|
+
async function prune(store, options = options_1.DEFAULT_RETENTION_OPTIONS, signal) {
|
|
21
20
|
if (!Number.isInteger(options.batchSize) || options.batchSize <= 0) {
|
|
22
21
|
throw new errors_1.InvalidRetentionOptionsError(`batchSize must be a positive integer, got ${options.batchSize}`);
|
|
23
22
|
}
|
|
@@ -25,26 +24,29 @@ async function prune(store, options = options_1.DEFAULT_RETENTION_OPTIONS) {
|
|
|
25
24
|
deleted: 0,
|
|
26
25
|
budget: options.maxBatchesPerPass,
|
|
27
26
|
drained: true,
|
|
28
|
-
});
|
|
27
|
+
}, signal);
|
|
29
28
|
return { deleted, drained };
|
|
30
29
|
}
|
|
31
|
-
async function pruneWindows(store, windows, options, state) {
|
|
30
|
+
async function pruneWindows(store, windows, options, state, signal) {
|
|
32
31
|
const [window, ...rest] = windows;
|
|
33
32
|
if (window === undefined) {
|
|
34
33
|
return state;
|
|
35
34
|
}
|
|
36
35
|
const windowBudget = state.budget <= 0 ? 0 : Math.max(state.budget - rest.length, 1);
|
|
37
|
-
const pruned = await pruneWindow(store, window, options.batchSize, windowBudget);
|
|
36
|
+
const pruned = await pruneWindow(store, window, options.batchSize, windowBudget, signal);
|
|
38
37
|
return await pruneWindows(store, rest, options, {
|
|
39
38
|
deleted: state.deleted + pruned.deleted,
|
|
40
39
|
budget: state.budget - pruned.batches,
|
|
41
40
|
drained: state.drained && pruned.drained,
|
|
42
|
-
});
|
|
41
|
+
}, signal);
|
|
43
42
|
}
|
|
44
|
-
async function pruneWindow(store, window, batchSize, budget) {
|
|
43
|
+
async function pruneWindow(store, window, batchSize, budget, signal) {
|
|
45
44
|
let deleted = 0;
|
|
46
45
|
let batches = 0;
|
|
47
46
|
while (batches < budget) {
|
|
47
|
+
if (signal?.aborted === true) {
|
|
48
|
+
return { deleted, batches, drained: false };
|
|
49
|
+
}
|
|
48
50
|
const affected = await store.deleteFinishedOlderThan({
|
|
49
51
|
statuses: window.statuses,
|
|
50
52
|
olderThanMs: window.olderThanSeconds * constants_1.Time.seconds.toMilliseconds,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../../src/core/retention/prune.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../../src/core/retention/prune.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TaskHandler } from './executor';
|
|
2
|
+
import type { MaterializerSummary } from './materializer';
|
|
3
|
+
import type { ReapResult } from './reaper';
|
|
4
|
+
import type { RetentionSummary } from './retention';
|
|
5
|
+
import type { ClaimedTask } from './types';
|
|
6
|
+
export interface Scheduler {
|
|
7
|
+
registerTaskHandler(taskType: string, handler: TaskHandler): void;
|
|
8
|
+
start(): void;
|
|
9
|
+
stop(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export interface SchedulerPasses {
|
|
12
|
+
materialize(signal?: AbortSignal): Promise<MaterializerSummary>;
|
|
13
|
+
execute(signal?: AbortSignal): Promise<ClaimedTask[]>;
|
|
14
|
+
reap(signal?: AbortSignal): Promise<ReapResult>;
|
|
15
|
+
prune(signal?: AbortSignal): Promise<RetentionSummary>;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../src/core/scheduler.ts"],"names":[],"mappings":""}
|