Skip to content

[BUGFIX] taskhelper: don't let the execution time delay the next cron execution - #383

Merged
Nexucis merged 1 commit into
perses:mainfrom
NopeCharon:fix/cron-precise-schedule
Nov 12, 2026
Merged

Nexucis merged 1 commit into
perses:mainfrom
NopeCharon:fix/cron-precise-schedule

Conversation

@NopeCharon

Copy link
Copy Markdown
Contributor

Description

Fixes #285.

The cron runner computes the next date from the moment an execution starts (the time received from the timer), but it then armed the next timer with next.Sub(now), where now is still that start time. So the timer waited the full interval counted from the end of the execution, and each execution was delayed by the time the previous one took. That's the behavior described in the issue: with a task every 5 minutes that runs for 5 seconds, it starts at 18:45:00, then 18:50:05, then 18:55:10, and so on.

The timer is now armed with time.Until(next), the time actually left until the next date. If an execution lasts longer than that, the next date has already passed and the task is executed again right away, the same way time.Ticker behaves for NewTick. The doc of NewCron now describes this.

The change is limited to the line arming the timer, so it doesn't conflict with the guard on the zero date proposed in #382.

Validation

  • New test TestCron_ExecutionTimeDoesNotDelayTheNextExecution with @every 1s, which checks the time between the start of two executions:
    • a task that takes 700ms is started every second. Without the fix, the gap is 1.7s.
    • a task that takes 1.5s is started again right away. Without the fix, the gap is 2s to 2.5s.
  • Both cases fail without the fix.
  • make test, golangci-lint v2.15.0 and make checkformat pass.

Checklist

  • Pull request has a descriptive title and context useful to a reviewer.
  • Pull request title follows the [<catalog_entry>] <commit message> naming convention.
  • All commits have DCO signoffs.

… execution

The cron runner computes the next date from the moment an execution
starts (the value received from the timer), but then armed the next
timer with `next.Sub(now)`, where `now` is still that start time. The
timer therefore waited the full interval counted from the end of the
execution, so every execution was delayed by the time the previous one
took. With a task scheduled every 5 minutes that runs for 5 seconds,
the task started at 18:45:00, then 18:50:05, then 18:55:10, and so on.

The timer is now armed with `time.Until(next)`, the time actually left
until the next date. If an execution lasts longer than that, the next
date has already passed and the task is executed again right away, as
`time.Ticker` does for NewTick.

The NewCron documentation now describes this behavior, and
TestCron_ExecutionTimeDoesNotDelayTheNextExecution checks the time
between the start of two executions with a task shorter and a task
longer than the schedule. Both cases fail without the fix.

Fixes perses#285

Signed-off-by: NopeCharon <115794254+NopeCharon@users.noreply.github.com>

@Nexucis Nexucis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you @NopeCharon !

@Nexucis
Nexucis merged commit 1e94c1b into perses:main Nov 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cron Task does not start at precise frequency

2 participants