mirror of
https://github.com/n8n-io/n8n
synced 2026-04-19 13:05:54 +02:00
refactor(core): harden deduplication key producer
This commit is contained in:
@@ -73,15 +73,11 @@ export class ScheduledTaskManager {
|
||||
}
|
||||
|
||||
let scheduledT: Date | null = null;
|
||||
const job = new CronJob(
|
||||
const job: CronJob = new CronJob(
|
||||
expression,
|
||||
() => {
|
||||
const firedFor = scheduledT;
|
||||
try {
|
||||
scheduledT = job.nextDate().toJSDate();
|
||||
} catch {
|
||||
scheduledT = null;
|
||||
}
|
||||
scheduledT = computeNext();
|
||||
|
||||
if (!this.instanceSettings.isLeader) return;
|
||||
if (firedFor === null) return;
|
||||
@@ -100,11 +96,21 @@ export class ScheduledTaskManager {
|
||||
timezone,
|
||||
);
|
||||
|
||||
try {
|
||||
scheduledT = job.nextDate().toJSDate();
|
||||
} catch {
|
||||
scheduledT = null;
|
||||
}
|
||||
const computeNext = (): Date | null => {
|
||||
try {
|
||||
return job.nextDate().toJSDate();
|
||||
} catch (error) {
|
||||
this.logger.warn('Failed to compute next scheduled fire time for cron; skipping tick', {
|
||||
workflowId,
|
||||
nodeId,
|
||||
expression,
|
||||
error,
|
||||
});
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
scheduledT = computeNext();
|
||||
|
||||
const cron: Cron = { job, summary, ctx };
|
||||
|
||||
|
||||
@@ -443,10 +443,13 @@ export class ScheduleTrigger implements INodeType {
|
||||
}
|
||||
}
|
||||
|
||||
const dedupEnabled = Container.get(ExecutionsConfig).scheduledExecutionDeduplicationEnabled;
|
||||
const workflowId = this.getWorkflow().id;
|
||||
const nodeId = this.getNode().id;
|
||||
|
||||
const configDedupEnabled =
|
||||
Container.get(ExecutionsConfig).scheduledExecutionDeduplicationEnabled;
|
||||
const dedupEnabled = configDedupEnabled && Boolean(workflowId);
|
||||
|
||||
const executeTrigger = (
|
||||
recurrence: IRecurrenceRule,
|
||||
skipRecurrenceCheck = false,
|
||||
|
||||
@@ -176,6 +176,10 @@ describe('ScheduleTrigger', () => {
|
||||
describe('deduplication key', () => {
|
||||
const executionsConfig = Container.get(ExecutionsConfig);
|
||||
|
||||
beforeEach(() => {
|
||||
executionsConfig.scheduledExecutionDeduplicationEnabled = false;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
executionsConfig.scheduledExecutionDeduplicationEnabled = false;
|
||||
});
|
||||
@@ -216,6 +220,26 @@ describe('ScheduleTrigger', () => {
|
||||
expect(scheduledT.getUTCMilliseconds()).toBe(0);
|
||||
});
|
||||
|
||||
it('should not emit a deduplication key when the workflow id is undefined', async () => {
|
||||
executionsConfig.scheduledExecutionDeduplicationEnabled = true;
|
||||
|
||||
const { emit } = await testTriggerNode(ScheduleTrigger, {
|
||||
timezone,
|
||||
node: {
|
||||
parameters: {
|
||||
rule: { interval: [{ field: 'cronExpression', expression: '0 */2 * * *' }] },
|
||||
},
|
||||
},
|
||||
workflowStaticData: {},
|
||||
workflow: { active: true },
|
||||
});
|
||||
|
||||
jest.advanceTimersByTime(2 * HOUR);
|
||||
|
||||
expect(emit).toHaveBeenCalledTimes(1);
|
||||
expect(emit.mock.calls[0][3]).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not emit a deduplication key when the feature flag is disabled', async () => {
|
||||
executionsConfig.scheduledExecutionDeduplicationEnabled = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user