From e362b6159cff7a724159aeba2df154bc87623607 Mon Sep 17 00:00:00 2001
From: Christoph Reiter <reiter.christoph@gmail.com>
Date: Tue, 14 Feb 2023 13:27:50 +0100
Subject: [PATCH] cron: don't run all jobs if there was no previous run

In case the API is started the first time, or it is re-deployed
and the cache is cleared/removed the API doesn't know when the
cron jobs were last checked.

Up until now it would assume that the last run was so long ago that
all jobs are due and run all jobs. This has the downside that on
a re-deploy all jobs are run, despite most of them not needing to.

This changes the defaults to not run any jobs if there is no previous
check recorded.

If the admin still wants to force run all jobs there is the "--force"
option that can be passed to the cron command.
---
 src/Cron/CronManager.php | 10 +++++++---
 tests/Cron/CronTest.php  |  4 ++--
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/src/Cron/CronManager.php b/src/Cron/CronManager.php
index de6a24a..ea221a6 100644
--- a/src/Cron/CronManager.php
+++ b/src/Cron/CronManager.php
@@ -53,9 +53,13 @@ final class CronManager implements LoggerAwareInterface
         $previousExpectedRun->setTimezone(new \DateTimeZone('UTC'));
 
         $shouldRun = false;
-        // If we were scheduled to run between now and the previous run (or just before of no previous run exists)
-        // then we should run
-        if ($previousExpectedRun <= $currentRun && ($previousRun === null || $previousExpectedRun > $previousRun)) {
+        if ($previousRun === null) {
+            // In case there is no previous run we just skip the cron job
+            // This can happen on re-deployments, and we don't want a cron-storm there, or jobs that run
+            // way off their schedule
+            $shouldRun = false;
+        } elseif ($previousExpectedRun > $previousRun && $previousExpectedRun <= $currentRun) {
+            // If we were scheduled to run between now and right the previous run then we should run
             $shouldRun = true;
         }
 
diff --git a/tests/Cron/CronTest.php b/tests/Cron/CronTest.php
index 10fd497..7c951cf 100644
--- a/tests/Cron/CronTest.php
+++ b/tests/Cron/CronTest.php
@@ -16,8 +16,8 @@ class CronTest extends TestCase
         $isDue = CronManager::isDue(new \DateTimeImmutable('2021-09-07T09:35:59Z'), new \DateTimeImmutable('2021-09-07T09:36:00Z'), '* * * * *');
         $this->assertTrue($isDue);
         $isDue = CronManager::isDue(null, new \DateTimeImmutable('2021-09-07T09:36:00Z'), '0 0 1 1 *');
-        $this->assertTrue($isDue);
+        $this->assertFalse($isDue);
         $isDue = CronManager::isDue(null, new \DateTimeImmutable('2021-09-07T09:36:00Z'), '* * * * *');
-        $this->assertTrue($isDue);
+        $this->assertFalse($isDue);
     }
 }
-- 
GitLab