@n8n/scheduler 0.2.2 → 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 +13 -24
- 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,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Timeline = void 0;
|
|
4
|
+
class Timeline {
|
|
5
|
+
constructor(intervalMs, jitterRatio, random, startAt) {
|
|
6
|
+
this.intervalMs = intervalMs;
|
|
7
|
+
this.jitterRatio = jitterRatio;
|
|
8
|
+
this.random = random;
|
|
9
|
+
this.slotAt = startAt + intervalMs * random();
|
|
10
|
+
}
|
|
11
|
+
get firstTickAt() {
|
|
12
|
+
return this.slotAt;
|
|
13
|
+
}
|
|
14
|
+
nextTickAt(now) {
|
|
15
|
+
const missedSlots = Math.floor(Math.max(0, now - this.slotAt) / this.intervalMs);
|
|
16
|
+
this.slotAt += (missedSlots + 1) * this.intervalMs;
|
|
17
|
+
const jitterMs = this.intervalMs * this.jitterRatio * (2 * this.random() - 1);
|
|
18
|
+
return this.slotAt + jitterMs;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.Timeline = Timeline;
|
|
22
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../../src/core/lifecycle/timeline.ts"],"names":[],"mappings":";;;AAWA,MAAa,QAAQ;IAIpB,YACkB,UAAkB,EAClB,WAAmB,EACnB,MAAoB,EACrC,OAAe;QAHE,eAAU,GAAV,UAAU,CAAQ;QAClB,gBAAW,GAAX,WAAW,CAAQ;QACnB,WAAM,GAAN,MAAM,CAAc;QAGrC,IAAI,CAAC,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,EAAE,CAAC;IAC/C,CAAC;IAGD,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;IAMD,UAAU,CAAC,GAAW;QACrB,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;QAC9E,OAAO,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC;IAC/B,CAAC;CACD;AA5BD,4BA4BC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { materialize, type MaterializerSummary, type MaterializerOptions, type OnJobPlanError, } from './materialize';
|
|
1
|
+
export { materialize, type MaterializerHooks, type MaterializerSummary, type MaterializerOptions, type OnJobPlanError, } from './materialize';
|
|
2
2
|
export { DEFAULT_MATERIALIZER_OPTIONS } from './options';
|
|
3
3
|
export { planOccurrences, type OccurrencePlan } from './plan';
|
|
4
|
-
export type { DueJobs, PlannedJob, RunInTransaction, MaterializerTransaction } from './transaction';
|
|
4
|
+
export type { DueJobs, NewOccurrence, PlannedJob, RecordedOccurrence, RecordOccurrencesResult, RunInTransaction, MaterializerTransaction, } from './transaction';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/materializer/index.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/materializer/index.ts"],"names":[],"mappings":";;;AAAA,6CAMuB;AALtB,0GAAA,WAAW,OAAA;AAMZ,qCAAyD;AAAhD,uHAAA,4BAA4B,OAAA;AACrC,+BAA8D;AAArD,uGAAA,eAAe,OAAA"}
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import type { ScheduledJob } from '../types';
|
|
2
2
|
import { type MaterializerOptions } from './options';
|
|
3
|
-
import type { RunInTransaction } from './transaction';
|
|
3
|
+
import type { RecordedOccurrence, RunInTransaction } from './transaction';
|
|
4
4
|
export type { MaterializerOptions } from './options';
|
|
5
5
|
export interface MaterializerSummary {
|
|
6
6
|
claimedJobs: number;
|
|
7
7
|
occurrences: number;
|
|
8
|
+
created: RecordedOccurrence[];
|
|
8
9
|
deferredJobs: number;
|
|
9
10
|
}
|
|
10
11
|
export type OnJobPlanError = (job: ScheduledJob, error: unknown) => void;
|
|
11
|
-
export
|
|
12
|
+
export interface MaterializerHooks {
|
|
13
|
+
onPlanError?: OnJobPlanError;
|
|
14
|
+
onSkippedDuplicates?: (context: {
|
|
15
|
+
planned: number;
|
|
16
|
+
recorded: number;
|
|
17
|
+
}) => void;
|
|
18
|
+
}
|
|
19
|
+
export declare function materialize(runInTransaction: RunInTransaction, options?: MaterializerOptions, hooks?: MaterializerHooks, signal?: AbortSignal): Promise<MaterializerSummary>;
|
|
@@ -4,22 +4,44 @@ exports.materialize = materialize;
|
|
|
4
4
|
const constants_1 = require("@n8n/constants");
|
|
5
5
|
const options_1 = require("./options");
|
|
6
6
|
const plan_1 = require("./plan");
|
|
7
|
-
async function materialize(runInTransaction, options = options_1.DEFAULT_MATERIALIZER_OPTIONS,
|
|
7
|
+
async function materialize(runInTransaction, options = options_1.DEFAULT_MATERIALIZER_OPTIONS, hooks = {}, signal) {
|
|
8
|
+
signal?.throwIfAborted();
|
|
8
9
|
return await runInTransaction(async (tx) => {
|
|
9
10
|
const claimed = await tx.claimDueJobs(options.batchSize);
|
|
11
|
+
signal?.throwIfAborted();
|
|
10
12
|
if (claimed === undefined) {
|
|
11
|
-
return { claimedJobs: 0, occurrences: 0, deferredJobs: 0 };
|
|
13
|
+
return { claimedJobs: 0, occurrences: 0, created: [], deferredJobs: 0 };
|
|
14
|
+
}
|
|
15
|
+
const { occurrencesPlanned, numberOfJobsDeferred } = planOrDeferJobs(claimed, options, hooks.onPlanError);
|
|
16
|
+
const rows = toNewOccurrences(occurrencesPlanned);
|
|
17
|
+
const { recorded, created } = await tx.recordOccurrences(rows);
|
|
18
|
+
signal?.throwIfAborted();
|
|
19
|
+
if (recorded < rows.length) {
|
|
20
|
+
try {
|
|
21
|
+
hooks.onSkippedDuplicates?.({ planned: rows.length, recorded });
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
}
|
|
12
25
|
}
|
|
13
|
-
const { occurrencesPlanned, numberOfJobsDeferred } = planOrDeferJobs(claimed, options, onPlanError);
|
|
14
|
-
const occurrences = await tx.recordOccurrences(occurrencesPlanned);
|
|
15
26
|
await tx.advanceJobs(occurrencesPlanned);
|
|
16
27
|
return {
|
|
17
28
|
claimedJobs: claimed.jobs.length,
|
|
18
|
-
occurrences,
|
|
29
|
+
occurrences: recorded,
|
|
30
|
+
created,
|
|
19
31
|
deferredJobs: numberOfJobsDeferred,
|
|
20
32
|
};
|
|
21
33
|
});
|
|
22
34
|
}
|
|
35
|
+
function toNewOccurrences(planned) {
|
|
36
|
+
return planned.flatMap(({ job, plan }) => plan.occurrences.map((when) => ({
|
|
37
|
+
jobId: job.id,
|
|
38
|
+
taskType: job.taskType,
|
|
39
|
+
payload: job.payload,
|
|
40
|
+
scheduledFor: when,
|
|
41
|
+
runAt: when,
|
|
42
|
+
maxAttempts: job.maxAttempts,
|
|
43
|
+
})));
|
|
44
|
+
}
|
|
23
45
|
function planOrDeferJobs(dueJobs, options, onPlanError) {
|
|
24
46
|
const plans = dueJobs.jobs.map((job) => planOrDeferJob(job, dueJobs.now, options, onPlanError));
|
|
25
47
|
return {
|
|
@@ -35,7 +57,11 @@ function planOrDeferJob(job, now, options, onPlanError) {
|
|
|
35
57
|
};
|
|
36
58
|
}
|
|
37
59
|
catch (error) {
|
|
38
|
-
|
|
60
|
+
try {
|
|
61
|
+
onPlanError?.(job, error);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
}
|
|
39
65
|
const retryAt = new Date(now.getTime() + options.planRetrySeconds * constants_1.Time.seconds.toMilliseconds);
|
|
40
66
|
return {
|
|
41
67
|
plannedJob: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materialize.js","sourceRoot":"","sources":["../../../src/core/materializer/materialize.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"materialize.js","sourceRoot":"","sources":["../../../src/core/materializer/materialize.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/core/materializer/options.ts"],"names":[],"mappings":";;;AAAA,8CAAsC;
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../../src/core/materializer/options.ts"],"names":[],"mappings":";;;AAAA,8CAAsC;AAqCzB,QAAA,4BAA4B,GAAwB;IAChE,aAAa,EAAE,EAAE;IACjB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,IAAI;IACf,gBAAgB,EAAE,gBAAI,CAAC,KAAK,CAAC,SAAS;IACtC,eAAe,EAAE,KAAK;CACtB,CAAC"}
|
|
@@ -3,19 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.planOccurrences = planOccurrences;
|
|
4
4
|
const constants_1 = require("@n8n/constants");
|
|
5
5
|
const next_run_1 = require("../recurrence/next-run");
|
|
6
|
+
const resolve_1 = require("../recurrence/resolve");
|
|
6
7
|
function planOccurrences(job, now, options) {
|
|
8
|
+
const schedule = (0, resolve_1.resolveSchedule)(job, options.defaultTimezone);
|
|
7
9
|
const windowEnd = now.getTime() + options.windowSeconds * constants_1.Time.seconds.toMilliseconds;
|
|
10
|
+
if (job.nextRunAt === null) {
|
|
11
|
+
return { occurrences: [], nextRunAt: null, lastFiredAt: job.lastFiredAt };
|
|
12
|
+
}
|
|
8
13
|
const occurrences = [];
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
const fires = (0, next_run_1.occurrencesFrom)(schedule, job.nextRunAt);
|
|
15
|
+
let fire = fires.next();
|
|
16
|
+
while (!fire.done &&
|
|
17
|
+
fire.value.getTime() <= windowEnd &&
|
|
12
18
|
occurrences.length < options.maxPerJob) {
|
|
13
|
-
occurrences.push(
|
|
14
|
-
|
|
19
|
+
occurrences.push(fire.value);
|
|
20
|
+
fire = fires.next();
|
|
15
21
|
}
|
|
16
22
|
return {
|
|
17
23
|
occurrences,
|
|
18
|
-
nextRunAt:
|
|
24
|
+
nextRunAt: fire.done ? null : fire.value,
|
|
19
25
|
lastFiredAt: occurrences.at(-1) ?? job.lastFiredAt,
|
|
20
26
|
};
|
|
21
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/core/materializer/plan.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/core/materializer/plan.ts"],"names":[],"mappings":";;AAgCA,0CA+BC;AA/DD,8CAAsC;AAEtC,qDAAyD;AACzD,mDAAwD;AA6BxD,SAAgB,eAAe,CAC9B,GAAiB,EACjB,GAAS,EACT,OAA8E;IAI9E,MAAM,QAAQ,GAAG,IAAA,yBAAe,EAAC,GAAG,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,aAAa,GAAG,gBAAI,CAAC,OAAO,CAAC,cAAc,CAAC;IAEtF,IAAI,GAAG,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;QAC5B,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;IAC3E,CAAC;IAED,MAAM,WAAW,GAAW,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,IAAA,0BAAe,EAAC,QAAQ,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC;IACvD,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACxB,OACC,CAAC,IAAI,CAAC,IAAI;QACV,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,SAAS;QACjC,WAAW,CAAC,MAAM,GAAG,OAAO,CAAC,SAAS,EACrC,CAAC;QACF,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;IAED,OAAO;QACN,WAAW;QACX,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;QACxC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,WAAW;KAClD,CAAC;AACH,CAAC"}
|
|
@@ -4,13 +4,30 @@ export interface PlannedJob {
|
|
|
4
4
|
job: ScheduledJob;
|
|
5
5
|
plan: OccurrencePlan;
|
|
6
6
|
}
|
|
7
|
+
export interface NewOccurrence {
|
|
8
|
+
jobId: number;
|
|
9
|
+
taskType: string;
|
|
10
|
+
payload: Record<string, unknown>;
|
|
11
|
+
scheduledFor: Date;
|
|
12
|
+
runAt: Date;
|
|
13
|
+
maxAttempts: number;
|
|
14
|
+
}
|
|
15
|
+
export interface RecordedOccurrence {
|
|
16
|
+
id: string;
|
|
17
|
+
jobId: number;
|
|
18
|
+
taskType: string;
|
|
19
|
+
}
|
|
20
|
+
export interface RecordOccurrencesResult {
|
|
21
|
+
recorded: number;
|
|
22
|
+
created: RecordedOccurrence[];
|
|
23
|
+
}
|
|
7
24
|
export interface DueJobs {
|
|
8
25
|
now: Date;
|
|
9
26
|
jobs: ScheduledJob[];
|
|
10
27
|
}
|
|
11
28
|
export interface MaterializerTransaction {
|
|
12
29
|
claimDueJobs(limit: number): Promise<DueJobs | undefined>;
|
|
13
|
-
recordOccurrences(
|
|
30
|
+
recordOccurrences(occurrences: NewOccurrence[]): Promise<RecordOccurrencesResult>;
|
|
14
31
|
advanceJobs(planned: PlannedJob[]): Promise<void>;
|
|
15
32
|
}
|
|
16
33
|
export type RunInTransaction = <T>(work: (tx: MaterializerTransaction) => Promise<T>) => Promise<T>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { provision, deprovision } from './provision';
|
|
2
|
+
export { createJobProvisioner } from './provisioner';
|
|
3
|
+
export type { JobProvisioner, JobProvisionerDeps } from './provisioner';
|
|
4
|
+
export type { ProvisionTransaction, RunInProvisionTransaction, DeprovisionTransaction, RunInDeprovisionTransaction, } from './transaction';
|
|
5
|
+
export type { ScheduleDefinition, CronDefinition, RecurringCronDefinition, IntervalDefinition, OneOffDefinition, DesiredJob, ExistingJob, ProvisionedJob, ProvisionSummary, } from './types';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createJobProvisioner = exports.deprovision = exports.provision = void 0;
|
|
4
|
+
var provision_1 = require("./provision");
|
|
5
|
+
Object.defineProperty(exports, "provision", { enumerable: true, get: function () { return provision_1.provision; } });
|
|
6
|
+
Object.defineProperty(exports, "deprovision", { enumerable: true, get: function () { return provision_1.deprovision; } });
|
|
7
|
+
var provisioner_1 = require("./provisioner");
|
|
8
|
+
Object.defineProperty(exports, "createJobProvisioner", { enumerable: true, get: function () { return provisioner_1.createJobProvisioner; } });
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/provisioning/index.ts"],"names":[],"mappings":";;;AAAA,yCAAqD;AAA5C,sGAAA,SAAS,OAAA;AAAE,wGAAA,WAAW,OAAA;AAC/B,6CAAqD;AAA5C,mHAAA,oBAAoB,OAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RunInProvisionTransaction, RunInDeprovisionTransaction } from './transaction';
|
|
2
|
+
import type { DesiredJob, ProvisionSummary } from './types';
|
|
3
|
+
export declare function provision(runInTransaction: RunInProvisionTransaction, desired: DesiredJob[]): Promise<ProvisionSummary>;
|
|
4
|
+
export declare function deprovision(runInTransaction: RunInDeprovisionTransaction): Promise<{
|
|
5
|
+
removed: number;
|
|
6
|
+
}>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.provision = provision;
|
|
4
|
+
exports.deprovision = deprovision;
|
|
5
|
+
const errors_1 = require("../errors");
|
|
6
|
+
async function provision(runInTransaction, desired) {
|
|
7
|
+
return await runInTransaction(async (tx) => {
|
|
8
|
+
const existing = await tx.findExisting();
|
|
9
|
+
const existingByName = new Map(existing.map((job) => [job.name, job]));
|
|
10
|
+
const desiredNames = new Set(desired.map((job) => job.name));
|
|
11
|
+
const inserts = [];
|
|
12
|
+
const redefined = [];
|
|
13
|
+
const unchanged = [];
|
|
14
|
+
for (const job of desired) {
|
|
15
|
+
const current = existingByName.get(job.name);
|
|
16
|
+
if (current === undefined) {
|
|
17
|
+
inserts.push(job);
|
|
18
|
+
}
|
|
19
|
+
else if (holdsDefinition(current, job)) {
|
|
20
|
+
unchanged.push({ id: current.id, name: current.name });
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
redefined.push({ id: current.id, name: current.name });
|
|
24
|
+
await tx.redefine(current.id, job.schedule, job.firstRunAt);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const removed = existing
|
|
28
|
+
.filter((job) => !desiredNames.has(job.name))
|
|
29
|
+
.map((job) => ({ id: job.id, name: job.name }));
|
|
30
|
+
await tx.withdrawPendingTasks(redefined.map((job) => job.id));
|
|
31
|
+
await tx.deleteJobs(removed.map((job) => job.id));
|
|
32
|
+
const insertedIds = await tx.insert(inserts);
|
|
33
|
+
const inserted = inserts.map((job, index) => ({ id: insertedIds[index], name: job.name }));
|
|
34
|
+
return { inserted, redefined, unchanged, removed };
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async function deprovision(runInTransaction) {
|
|
38
|
+
return await runInTransaction(async (tx) => ({ removed: await tx.deleteAll() }));
|
|
39
|
+
}
|
|
40
|
+
function holdsDefinition(current, desired) {
|
|
41
|
+
return (sameSchedule(current.schedule, desired.schedule) &&
|
|
42
|
+
current.hasClock === (desired.firstRunAt !== null));
|
|
43
|
+
}
|
|
44
|
+
function sameSchedule(a, b) {
|
|
45
|
+
switch (a.kind) {
|
|
46
|
+
case 'cron':
|
|
47
|
+
return (b.kind === 'cron' && a.cronExpression === b.cronExpression && a.timezone === b.timezone);
|
|
48
|
+
case 'recurring_cron':
|
|
49
|
+
return (b.kind === 'recurring_cron' &&
|
|
50
|
+
a.cronExpression === b.cronExpression &&
|
|
51
|
+
a.timezone === b.timezone &&
|
|
52
|
+
a.recurrenceUnit === b.recurrenceUnit &&
|
|
53
|
+
a.recurrenceSize === b.recurrenceSize);
|
|
54
|
+
case 'interval':
|
|
55
|
+
return b.kind === 'interval' && a.intervalSeconds === b.intervalSeconds;
|
|
56
|
+
case 'one_off':
|
|
57
|
+
return b.kind === 'one_off' && a.fireAt.getTime() === b.fireAt.getTime();
|
|
58
|
+
default: {
|
|
59
|
+
const exhaustive = a;
|
|
60
|
+
throw new errors_1.InvalidScheduleError(`Unexpected schedule kind: ${JSON.stringify(exhaustive)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=provision.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provision.js","sourceRoot":"","sources":["../../../src/core/provisioning/provision.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { RunInDeprovisionTransaction, RunInProvisionTransaction } from './transaction';
|
|
2
|
+
import type { DesiredJob, ProvisionSummary } from './types';
|
|
3
|
+
import { type Tracer } from '../../observability/tracer';
|
|
4
|
+
export interface JobProvisioner<PScope, DScope = PScope> {
|
|
5
|
+
provision(scope: PScope, desired: DesiredJob[]): Promise<ProvisionSummary>;
|
|
6
|
+
deprovision(scope: DScope): Promise<{
|
|
7
|
+
removed: number;
|
|
8
|
+
}>;
|
|
9
|
+
}
|
|
10
|
+
export interface JobProvisionerDeps<PScope, DScope = PScope> {
|
|
11
|
+
provisionTransaction: (scope: PScope) => RunInProvisionTransaction;
|
|
12
|
+
deprovisionTransaction: (scope: DScope) => RunInDeprovisionTransaction;
|
|
13
|
+
tracer?: Tracer;
|
|
14
|
+
}
|
|
15
|
+
export declare function createJobProvisioner<PScope, DScope = PScope>(deps: JobProvisionerDeps<PScope, DScope>): JobProvisioner<PScope, DScope>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createJobProvisioner = createJobProvisioner;
|
|
4
|
+
const provision_1 = require("./provision");
|
|
5
|
+
const provisioner_tracing_1 = require("../../observability/provisioner-tracing");
|
|
6
|
+
const tracer_1 = require("../../observability/tracer");
|
|
7
|
+
function createJobProvisioner(deps) {
|
|
8
|
+
const tracing = (0, provisioner_tracing_1.createProvisionerTracing)(deps.tracer ?? tracer_1.noopTracer);
|
|
9
|
+
return {
|
|
10
|
+
async provision(scope, desired) {
|
|
11
|
+
return await tracing.provision(async () => await (0, provision_1.provision)(deps.provisionTransaction(scope), desired));
|
|
12
|
+
},
|
|
13
|
+
async deprovision(scope) {
|
|
14
|
+
return await tracing.deprovision(async () => await (0, provision_1.deprovision)(deps.deprovisionTransaction(scope)));
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=provisioner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provisioner.js","sourceRoot":"","sources":["../../../src/core/provisioning/provisioner.ts"],"names":[],"mappings":";;AAsCA,oDAgBC;AAtDD,2CAAqD;AAGrD,iFAAmF;AACnF,uDAAqE;AAkCrE,SAAgB,oBAAoB,CACnC,IAAwC;IAExC,MAAM,OAAO,GAAG,IAAA,8CAAwB,EAAC,IAAI,CAAC,MAAM,IAAI,mBAAU,CAAC,CAAC;IACpE,OAAO;QACN,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO;YAC7B,OAAO,MAAM,OAAO,CAAC,SAAS,CAC7B,KAAK,IAAI,EAAE,CAAC,MAAM,IAAA,qBAAS,EAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,CACtE,CAAC;QACH,CAAC;QACD,KAAK,CAAC,WAAW,CAAC,KAAK;YACtB,OAAO,MAAM,OAAO,CAAC,WAAW,CAC/B,KAAK,IAAI,EAAE,CAAC,MAAM,IAAA,uBAAW,EAAC,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC,CACjE,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DesiredJob, ExistingJob, ScheduleDefinition } from './types';
|
|
2
|
+
export interface ProvisionTransaction {
|
|
3
|
+
findExisting(): Promise<ExistingJob[]>;
|
|
4
|
+
insert(jobs: DesiredJob[]): Promise<number[]>;
|
|
5
|
+
redefine(jobId: number, schedule: ScheduleDefinition, nextRunAt: Date | null): Promise<void>;
|
|
6
|
+
withdrawPendingTasks(jobIds: number[]): Promise<void>;
|
|
7
|
+
deleteJobs(jobIds: number[]): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export type RunInProvisionTransaction = <T>(work: (tx: ProvisionTransaction) => Promise<T>) => Promise<T>;
|
|
10
|
+
export interface DeprovisionTransaction {
|
|
11
|
+
deleteAll(): Promise<number>;
|
|
12
|
+
}
|
|
13
|
+
export type RunInDeprovisionTransaction = <T>(work: (tx: DeprovisionTransaction) => Promise<T>) => Promise<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../../src/core/provisioning/transaction.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { RecurringCronUnit } from '@n8n/constants';
|
|
2
|
+
export type ScheduleDefinition = CronDefinition | RecurringCronDefinition | IntervalDefinition | OneOffDefinition;
|
|
3
|
+
export interface CronDefinition {
|
|
4
|
+
kind: 'cron';
|
|
5
|
+
cronExpression: string;
|
|
6
|
+
timezone: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface RecurringCronDefinition {
|
|
9
|
+
kind: 'recurring_cron';
|
|
10
|
+
cronExpression: string;
|
|
11
|
+
timezone: string | null;
|
|
12
|
+
recurrenceUnit: RecurringCronUnit;
|
|
13
|
+
recurrenceSize: number;
|
|
14
|
+
}
|
|
15
|
+
export interface IntervalDefinition {
|
|
16
|
+
kind: 'interval';
|
|
17
|
+
intervalSeconds: number;
|
|
18
|
+
}
|
|
19
|
+
export interface OneOffDefinition {
|
|
20
|
+
kind: 'one_off';
|
|
21
|
+
fireAt: Date;
|
|
22
|
+
}
|
|
23
|
+
export interface DesiredJob {
|
|
24
|
+
name: string;
|
|
25
|
+
schedule: ScheduleDefinition;
|
|
26
|
+
firstRunAt: Date | null;
|
|
27
|
+
}
|
|
28
|
+
export interface ExistingJob {
|
|
29
|
+
id: number;
|
|
30
|
+
name: string;
|
|
31
|
+
schedule: ScheduleDefinition;
|
|
32
|
+
hasClock: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface ProvisionedJob {
|
|
35
|
+
id: number;
|
|
36
|
+
name: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ProvisionSummary {
|
|
39
|
+
inserted: ProvisionedJob[];
|
|
40
|
+
redefined: ProvisionedJob[];
|
|
41
|
+
unchanged: ProvisionedJob[];
|
|
42
|
+
removed: ProvisionedJob[];
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/provisioning/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { reap, DEFAULT_REAPER_OPTIONS, type ReapResult, type ReaperOptions, type ReaperTaskStore, type ExpiredLeaseRef, type ExpiredLeaseRow, type ReaperHooks, } from './reap';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_REAPER_OPTIONS = exports.reap = void 0;
|
|
4
|
+
var reap_1 = require("./reap");
|
|
5
|
+
Object.defineProperty(exports, "reap", { enumerable: true, get: function () { return reap_1.reap; } });
|
|
6
|
+
Object.defineProperty(exports, "DEFAULT_REAPER_OPTIONS", { enumerable: true, get: function () { return reap_1.DEFAULT_REAPER_OPTIONS; } });
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/reaper/index.ts"],"names":[],"mappings":";;;AAAA,+BASgB;AARf,4FAAA,IAAI,OAAA;AACJ,8GAAA,sBAAsB,OAAA"}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import type { Logger } from '@n8n/backend-common';
|
|
2
1
|
export interface ReapResult {
|
|
3
2
|
reclaimed: number;
|
|
4
3
|
deadLettered: number;
|
|
5
4
|
}
|
|
6
|
-
interface ExpiredLeaseRef {
|
|
5
|
+
export interface ExpiredLeaseRef {
|
|
7
6
|
id: string;
|
|
8
7
|
claimedEpoch: number;
|
|
9
8
|
}
|
|
10
|
-
interface ExpiredLeaseRow {
|
|
9
|
+
export interface ExpiredLeaseRow {
|
|
11
10
|
id: string;
|
|
12
11
|
attempts: number;
|
|
13
12
|
maxAttempts: number;
|
|
@@ -18,10 +17,16 @@ export interface ReaperTaskStore {
|
|
|
18
17
|
reclaimExpired(ref: ExpiredLeaseRef, backoffMs: number, errorMessage: string): Promise<number>;
|
|
19
18
|
deadLetterExpired(ref: ExpiredLeaseRef, errorMessage: string): Promise<number>;
|
|
20
19
|
}
|
|
21
|
-
export interface
|
|
22
|
-
store: ReaperTaskStore;
|
|
23
|
-
logger: Logger;
|
|
20
|
+
export interface ReaperOptions {
|
|
24
21
|
batchSize: number;
|
|
25
22
|
}
|
|
26
|
-
export declare
|
|
27
|
-
export {
|
|
23
|
+
export declare const DEFAULT_REAPER_OPTIONS: ReaperOptions;
|
|
24
|
+
export interface ReaperHooks {
|
|
25
|
+
onRowError?: (taskId: string, error: unknown) => void;
|
|
26
|
+
onDeadLetter?: (task: {
|
|
27
|
+
taskId: string;
|
|
28
|
+
attempts: number;
|
|
29
|
+
maxAttempts: number;
|
|
30
|
+
}) => void;
|
|
31
|
+
}
|
|
32
|
+
export declare function reap(store: ReaperTaskStore, options?: ReaperOptions, hooks?: ReaperHooks, signal?: AbortSignal): Promise<ReapResult>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_REAPER_OPTIONS = void 0;
|
|
4
|
+
exports.reap = reap;
|
|
5
|
+
const backoff_1 = require("../executor/backoff");
|
|
6
|
+
const LEASE_EXPIRED_MESSAGE = 'Lease expired before completion';
|
|
7
|
+
exports.DEFAULT_REAPER_OPTIONS = {
|
|
8
|
+
batchSize: 100,
|
|
9
|
+
};
|
|
10
|
+
async function reap(store, options = exports.DEFAULT_REAPER_OPTIONS, hooks = {}, signal) {
|
|
11
|
+
const expired = await store.findExpiredLeases(options.batchSize);
|
|
12
|
+
if (expired.length === 0)
|
|
13
|
+
return { reclaimed: 0, deadLettered: 0 };
|
|
14
|
+
let reclaimed = 0;
|
|
15
|
+
let deadLettered = 0;
|
|
16
|
+
for (const task of expired) {
|
|
17
|
+
if (signal?.aborted === true) {
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const nextAttempts = task.attempts + 1;
|
|
22
|
+
if (nextAttempts >= task.maxAttempts) {
|
|
23
|
+
const affected = await store.deadLetterExpired({ id: task.id, claimedEpoch: task.leaseEpoch }, LEASE_EXPIRED_MESSAGE);
|
|
24
|
+
deadLettered += affected;
|
|
25
|
+
if (affected > 0) {
|
|
26
|
+
try {
|
|
27
|
+
hooks.onDeadLetter?.({
|
|
28
|
+
taskId: task.id,
|
|
29
|
+
attempts: nextAttempts,
|
|
30
|
+
maxAttempts: task.maxAttempts,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
reclaimed += await store.reclaimExpired({ id: task.id, claimedEpoch: task.leaseEpoch }, (0, backoff_1.backoff)(nextAttempts), LEASE_EXPIRED_MESSAGE);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
try {
|
|
43
|
+
hooks.onRowError?.(task.id, error);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { reclaimed, deadLettered };
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=reap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reap.js","sourceRoot":"","sources":["../../../src/core/reaper/reap.ts"],"names":[],"mappings":";;;AAoFA,oBA+DC;AAnJD,iDAA8C;AAG9C,MAAM,qBAAqB,GAAG,iCAAiC,CAAC;AA4CnD,QAAA,sBAAsB,GAAkB;IACpD,SAAS,EAAE,GAAG;CACd,CAAC;AAmCK,KAAK,UAAU,IAAI,CACzB,KAAsB,EACtB,UAAyB,8BAAsB,EAC/C,QAAqB,EAAE,EACvB,MAAoB;IAEpB,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,iBAAiB,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAGjE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,SAAS,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IAEnE,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,MAAM,EAAE,OAAO,KAAK,IAAI,EAAE,CAAC;YAC9B,MAAM;QACP,CAAC;QAGD,IAAI,CAAC;YAGJ,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;YACvC,IAAI,YAAY,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACtC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,CAC7C,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,EAC9C,qBAAqB,CACrB,CAAC;gBACF,YAAY,IAAI,QAAQ,CAAC;gBAGzB,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;oBAClB,IAAI,CAAC;wBAGJ,KAAK,CAAC,YAAY,EAAE,CAAC;4BACpB,MAAM,EAAE,IAAI,CAAC,EAAE;4BACf,QAAQ,EAAE,YAAY;4BACtB,WAAW,EAAE,IAAI,CAAC,WAAW;yBAC7B,CAAC,CAAC;oBACJ,CAAC;oBAAC,MAAM,CAAC;oBAET,CAAC;gBACF,CAAC;YACF,CAAC;iBAAM,CAAC;gBACP,SAAS,IAAI,MAAM,KAAK,CAAC,cAAc,CACtC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,UAAU,EAAE,EAC9C,IAAA,iBAAO,EAAC,YAAY,CAAC,EACrB,qBAAqB,CACrB,CAAC;YACH,CAAC;QACF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC;gBAGJ,KAAK,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YACpC,CAAC;YAAC,MAAM,CAAC;YAET,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.required = required;
|
|
4
|
+
const errors_1 = require("../errors");
|
|
5
|
+
function required(job, key) {
|
|
6
|
+
const value = job[key];
|
|
7
|
+
if (value === null || value === undefined) {
|
|
8
|
+
throw new errors_1.CorruptStorageRowError(`scheduled_job ${job.id} of kind '${job.kind}' is missing '${String(key)}'`);
|
|
9
|
+
}
|
|
10
|
+
return value;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=field.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field.js","sourceRoot":"","sources":["../../../src/core/recurrence/field.ts"],"names":[],"mappings":";;AAaA,4BAWC;AAxBD,sCAAmD;AAanD,SAAgB,QAAQ,CACvB,GAAiB,EACjB,GAAM;IAEN,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,IAAI,+BAAsB,CAC/B,iBAAiB,GAAG,CAAC,EAAE,aAAa,GAAG,CAAC,IAAI,iBAAiB,MAAM,CAAC,GAAG,CAAC,GAAG,CAC3E,CAAC;IACH,CAAC;IACD,OAAO,KAAqC,CAAC;AAC9C,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CronExpressionParser } from 'cron-parser';
|
|
2
|
+
import type { CronExpression } from 'n8n-workflow';
|
|
3
|
+
import type { CronSchedule, RecurringCronSchedule, ScheduledJob } from '../../types';
|
|
4
|
+
export type CronCursor = ReturnType<typeof CronExpressionParser.parse>;
|
|
5
|
+
export declare function validateCron(schedule: CronSchedule | RecurringCronSchedule): void;
|
|
6
|
+
export declare function resolvedTimezone(schedule: CronSchedule | RecurringCronSchedule): string;
|
|
7
|
+
export declare function parseCron(cronExpression: CronExpression, after: Date, timezone: string): CronCursor;
|
|
8
|
+
export declare function cronNextRun(schedule: CronSchedule | RecurringCronSchedule, after: Date): Date;
|
|
9
|
+
export declare function cronOccurrences(schedule: CronSchedule, first: Date): Generator<Date>;
|
|
10
|
+
export declare function resolveCron(job: ScheduledJob, defaultTimezone: string): CronSchedule;
|