From 1c3e855c65f9f8f885e1dde3e513fc1991c4e079 Mon Sep 17 00:00:00 2001 From: Marcel Werk Date: Fri, 15 Jul 2016 17:02:48 +0200 Subject: [PATCH] Improved loading of outstanding cronjobs --- .../system/cronjob/CronjobScheduler.class.php | 88 ++++++++++--------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/wcfsetup/install/files/lib/system/cronjob/CronjobScheduler.class.php b/wcfsetup/install/files/lib/system/cronjob/CronjobScheduler.class.php index 1c6c6c402d..00307c4dbe 100644 --- a/wcfsetup/install/files/lib/system/cronjob/CronjobScheduler.class.php +++ b/wcfsetup/install/files/lib/system/cronjob/CronjobScheduler.class.php @@ -109,52 +109,56 @@ class CronjobScheduler extends SingletonFactory { * Loads outstanding cronjobs. */ protected function loadCronjobs() { - $sql = "SELECT * - FROM wcf".WCF_N."_cronjob cronjob - WHERE (cronjob.nextExec <= ? OR cronjob.afterNextExec <= ?) - AND cronjob.isDisabled = ? - AND cronjob.failCount < ?"; - $statement = WCF::getDB()->prepareStatement($sql); - $statement->execute([ - TIME_NOW, - TIME_NOW, - 0, - Cronjob::MAX_FAIL_COUNT - ]); - while ($row = $statement->fetchArray()) { - $cronjob = new Cronjob(null, $row); - $cronjobEditor = new CronjobEditor($cronjob); - $executeCronjob = true; - - $data = [ - 'state' => Cronjob::PENDING - ]; - - // reset cronjob if it got stuck before and afterNextExec is in the past - if ($cronjobEditor->afterNextExec <= TIME_NOW) { - if ($cronjobEditor->state == Cronjob::EXECUTING) { - $failCount = $cronjobEditor->failCount + 1; - $data['failCount'] = $failCount; - - // disable cronjob - if ($failCount == Cronjob::MAX_FAIL_COUNT) { - $data['isDisabled'] = 1; - $data['state'] = 0; + WCF::getDB()->beginTransaction(); + $committed = false; + try { + $sql = "SELECT * + FROM wcf" . WCF_N . "_cronjob cronjob + WHERE (cronjob.nextExec <= ? OR cronjob.afterNextExec <= ?) + AND cronjob.isDisabled = ? + AND cronjob.failCount < ? + FOR UPDATE"; + $statement = WCF::getDB()->prepareStatement($sql); + $statement->execute([TIME_NOW, TIME_NOW, 0, Cronjob::MAX_FAIL_COUNT]); + while ($row = $statement->fetchArray()) { + $cronjob = new Cronjob(null, $row); + $cronjobEditor = new CronjobEditor($cronjob); + $executeCronjob = true; + + $data = ['state' => Cronjob::PENDING]; + + // reset cronjob if it got stuck before and afterNextExec is in the past + if ($cronjobEditor->afterNextExec <= TIME_NOW) { + if ($cronjobEditor->state == Cronjob::EXECUTING) { + $failCount = $cronjobEditor->failCount + 1; + $data['failCount'] = $failCount; + + // disable cronjob + if ($failCount == Cronjob::MAX_FAIL_COUNT) { + $data['isDisabled'] = 1; + $data['state'] = 0; + $executeCronjob = false; + } + } + } // ignore cronjobs which seem to be running + else { + if ($cronjobEditor->nextExec <= TIME_NOW && $cronjobEditor->state != Cronjob::READY) { $executeCronjob = false; } } + + // mark cronjob as pending, preventing parallel execution + $cronjobEditor->update($data); + + if ($executeCronjob) { + $this->cronjobEditors[] = $cronjobEditor; + } } - // ignore cronjobs which seem to be running - else if ($cronjobEditor->nextExec <= TIME_NOW && $cronjobEditor->state != Cronjob::READY) { - $executeCronjob = false; - } - - // mark cronjob as pending, preventing parallel execution - $cronjobEditor->update($data); - - if ($executeCronjob) { - $this->cronjobEditors[] = $cronjobEditor; - } + WCF::getDB()->commitTransaction(); + $committed = true; + } + finally { + if (!$committed) WCF::getDB()->rollBackTransaction(); } } -- 2.20.1