fix(core): Remove unused N8N_SCHEDULER_MIN_INTERVAL setting (#41194)

This commit is contained in:
Mike Repeć 2026-10-15 12:29:35 +00:00 committed by GitHub
parent 154cd63bbc
commit c839d6cd49
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 6 additions and 54 deletions

View File

@ -32,7 +32,6 @@ describe('SchedulerConfig', () => {
expect(scheduler.retentionSeconds).toBe(24 * 60 * 60);
expect(scheduler.failedRetentionSeconds).toBe(7 * 24 * 60 * 60);
expect(scheduler.retentionIntervalSeconds).toBe(60 * 60);
expect(scheduler.minIntervalSeconds).toBe(0);
expect(scheduler.jitterRatio).toBe(0.1);
expect(scheduler.materializationTimeoutSeconds).toBe(60);
expect(scheduler.executorTimeoutSeconds).toBe(60);
@ -74,7 +73,6 @@ describe('SchedulerConfig', () => {
vi.stubEnv('N8N_SCHEDULER_RETENTION', '43200');
vi.stubEnv('N8N_SCHEDULER_FAILED_RETENTION', '86400');
vi.stubEnv('N8N_SCHEDULER_RETENTION_INTERVAL', '600');
vi.stubEnv('N8N_SCHEDULER_MIN_INTERVAL', '15');
vi.stubEnv('N8N_SCHEDULER_JITTER_RATIO', '0.25');
vi.stubEnv('N8N_SCHEDULER_MATERIALIZATION_TIMEOUT', '30');
vi.stubEnv('N8N_SCHEDULER_EXECUTOR_TIMEOUT', '15');
@ -97,7 +95,6 @@ describe('SchedulerConfig', () => {
expect(scheduler.retentionSeconds).toBe(43200);
expect(scheduler.failedRetentionSeconds).toBe(86400);
expect(scheduler.retentionIntervalSeconds).toBe(600);
expect(scheduler.minIntervalSeconds).toBe(15);
expect(scheduler.jitterRatio).toBe(0.25);
expect(scheduler.materializationTimeoutSeconds).toBe(30);
expect(scheduler.executorTimeoutSeconds).toBe(15);
@ -128,13 +125,5 @@ describe('SchedulerConfig', () => {
expect(scheduler.taskTimeoutSeconds).toBe(300);
});
it('should allow disabling the min-interval clamp with 0', () => {
vi.stubEnv('N8N_SCHEDULER_MIN_INTERVAL', '0');
const { scheduler } = Container.get(GlobalConfig);
expect(scheduler.minIntervalSeconds).toBe(0);
});
});
});

View File

@ -4,12 +4,6 @@ import { z } from 'zod';
import { Config, Env } from '../decorators';
import { positiveIntSchema } from '../schemas';
/**
* Allows 0 (the clamp disabled) in addition to any positive value. Used for a
* setting where 0 is a meaningful "off", not just a smaller number.
*/
const nonNegativeIntSchema = z.number({ coerce: true }).int().nonnegative();
/**
* A jitter ratio: a fraction in [0, 1). 0 disables jitter; 1 or above would
* allow a zero or negative delay between ticks, so they are rejected.
@ -233,18 +227,6 @@ export class SchedulerConfig {
@Env('N8N_SCHEDULER_JITTER_RATIO', jitterRatioSchema)
jitterRatio: number = 0.1;
/**
* The smallest gap, in seconds, allowed between consecutive runs of the same
* schedule. A schedule set to run more often than this is slowed down to this
* gap. Defaults to 0, which disables the limit and honours whatever interval
* each schedule specifies.
*
* Set it to put a floor on how frequently any schedule can run, for example to
* stop a misconfigured every-second schedule from overloading the instance.
*/
@Env('N8N_SCHEDULER_MIN_INTERVAL', nonNegativeIntSchema)
minIntervalSeconds: number = 0;
/**
* How a Schedule Trigger node's "every N seconds/minutes" schedules run under
* the durable scheduler. Defaults to `new`.

View File

@ -513,7 +513,6 @@ describe('GlobalConfig', () => {
retentionIntervalSeconds: 3600,
retentionTimeoutSeconds: 300,
jitterRatio: 0.1,
minIntervalSeconds: 0,
maxConcurrentPasses: 10,
triggerNodeMode: 'new',
enabledForPollTriggers: false,

View File

@ -32,7 +32,6 @@ describe('DurableScheduler', () => {
instanceType = 'main',
dbType = 'sqlite',
materializationIntervalSeconds = 10,
minIntervalSeconds = 0,
executorIntervalSeconds = 5,
materializationWindowSeconds = 60,
misfireGraceSeconds = 60,
@ -72,7 +71,6 @@ describe('DurableScheduler', () => {
executorIntervalSeconds,
jitterRatio: 0.1,
materializationIntervalSeconds,
minIntervalSeconds,
materializationWindowSeconds,
misfireGraceSeconds,
enabledForPollTriggers,
@ -137,8 +135,8 @@ describe('DurableScheduler', () => {
describe('drain rate warning', () => {
it('warns when a pass cannot drain the fastest possible schedule before the next one is due', () => {
// maxPerJob is 1000: a schedule as fast as this instance allows (the default
// floor of one second) can outrun a 1001s materialization interval.
// maxPerJob is 1000: a one-second schedule can outrun a 1001s materialization
// interval.
const { logger } = makeScheduler({ materializationIntervalSeconds: 1001 });
expect(logger.warn).toHaveBeenCalledWith(
@ -155,20 +153,6 @@ describe('DurableScheduler', () => {
expect.anything(),
);
});
it('scales the threshold by an operator-configured minimum interval floor', () => {
// A 60s floor makes 1001s safe again: even the fastest schedule now
// produces at most one occurrence per 60s, well within maxPerJob's reach.
const { logger } = makeScheduler({
materializationIntervalSeconds: 1001,
minIntervalSeconds: 60,
});
expect(logger.warn).not.toHaveBeenCalledWith(
expect.stringContaining('materialization interval'),
expect.anything(),
);
});
});
describe('misfire grace warning', () => {

View File

@ -179,15 +179,13 @@ function warnOnMisfireGrace(logger: Logger, config: GlobalConfig['scheduler']):
* running.
*/
function warnOnDrainRate(logger: Logger, config: GlobalConfig['scheduler']): void {
const { materializationIntervalSeconds, minIntervalSeconds } = config;
// The fastest a schedule can legally fire: the operator's floor if they set
// one, otherwise the fastest an interval can be at all.
const fastestIntervalSeconds = minIntervalSeconds > 0 ? minIntervalSeconds : 1;
const drainSeconds = DEFAULT_MATERIALIZER_OPTIONS.maxPerJob * fastestIntervalSeconds;
const { materializationIntervalSeconds } = config;
// The fastest a schedule can fire is once per second.
const drainSeconds = DEFAULT_MATERIALIZER_OPTIONS.maxPerJob;
if (materializationIntervalSeconds > drainSeconds) {
logger.warn(
'Scheduler materialization interval is long enough that a pass may never fully drain the busiest possible schedule; under the coalesce misfire policy such a schedule could stop producing catch-up runs entirely',
{ materializationIntervalSeconds, fastestIntervalSeconds },
{ materializationIntervalSeconds },
);
}
}