From 955a94638ce7084c8e2a87489d4a330af708187e Mon Sep 17 00:00:00 2001 From: Schalli Date: Sat, 27 Jun 2026 17:20:11 +0200 Subject: [PATCH] fix(07): CR-02 correct cron expression for pollIntervalMin >= 60 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Values >=60 in the cron minute field silently misbehave (*/60 fires once per hour, */90 fires once per hour, etc.). Use the hours field for intervals >=60: <60 min → */N * * * * >=60 min → 0 */H * * * (H = floor(N/60)) Also adds @Max(1440) to DkvConfigDto to bound the field at 24 h. --- apps/api/src/dkv/dkv-scheduler.service.ts | 11 +++++++++-- apps/api/src/dkv/dto/dkv-config.dto.ts | 4 +++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/api/src/dkv/dkv-scheduler.service.ts b/apps/api/src/dkv/dkv-scheduler.service.ts index 80d7990..5096ca0 100644 --- a/apps/api/src/dkv/dkv-scheduler.service.ts +++ b/apps/api/src/dkv/dkv-scheduler.service.ts @@ -101,8 +101,15 @@ export class DkvSchedulerService implements OnModuleInit { /* Job not yet registered — this is expected on first call */ } - // Create new cron job with computed expression: every N minutes - const cronExpr = `*/${intervalMin} * * * *`; + // Create new cron job with computed expression. + // Standard cron minute field only accepts 0–59; for longer intervals use the hours field. + let cronExpr: string; + if (intervalMin < 60) { + cronExpr = `*/${intervalMin} * * * *`; // e.g. */15 * * * * + } else { + const hours = Math.floor(intervalMin / 60); + cronExpr = `0 */${hours} * * *`; // e.g. 0 */2 * * * + } const job = new CronJobClass(cronExpr, () => { this.dkvService.processInbox(tenant).catch((err) => this.logger.error( diff --git a/apps/api/src/dkv/dto/dkv-config.dto.ts b/apps/api/src/dkv/dto/dkv-config.dto.ts index 06eb381..6ff8a93 100644 --- a/apps/api/src/dkv/dto/dkv-config.dto.ts +++ b/apps/api/src/dkv/dto/dkv-config.dto.ts @@ -72,11 +72,13 @@ export class DkvConfigDto { /** * Polling interval in minutes. Minimum 5 minutes to prevent DoS via excessive polling - * (T-07-05, UI-SPEC minimum = 5). + * (T-07-05, UI-SPEC minimum = 5). Maximum 1440 (24 h) — values above 59 use the cron + * hours field (must be a factor of 24 for predictable hourly+ behaviour). */ @IsOptional() @IsInt() @Min(5) + @Max(1440) pollIntervalMin?: number; /**