From ae0c4c00df8ec2892f28ba70a138a94909a3550d Mon Sep 17 00:00:00 2001 From: Eric Espie Date: Wed, 4 Jan 2023 08:57:21 +0100 Subject: [PATCH] =?UTF-8?q?N=C2=B04692=20-=20Enable=20parallelization=20of?= =?UTF-8?q?=20multiple=20CRON=20jobs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webservices/cron.php | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/webservices/cron.php b/webservices/cron.php index 9f416f20d..e2dd34a2b 100644 --- a/webservices/cron.php +++ b/webservices/cron.php @@ -171,6 +171,8 @@ function RunTask(BackgroundTask $oTask, $iTimeLimit) } /** + * + * @param bool $bDebug * * @throws \ArchivedObjectException * @throws \CoreCannotSaveObjectException @@ -189,9 +191,19 @@ function CronExec($bDebug) $iMaxDuration = MetaModel::GetConfig()->Get('cron_max_execution_time'); $iTimeLimit = $iStarted + $iMaxDuration; $iCronSleep = MetaModel::GetConfig()->Get('cron_sleep'); - $iMaxCronProcess = MetaModel::GetConfig()->Get('cron.max_processes'); + $iMaxCronProcess = max(MetaModel::GetConfig()->Get('cron.max_processes'), 1); + + // Allow a time slot for every task + // knowing that there are $iMaxCronProcess running in parallel for the amount of tasks + $oSearch = new DBObjectSearch('BackgroundTask'); + $oSearch->AddCondition('status', 'active'); + $oTasks = new DBObjectSet($oSearch); + $iCount = $oTasks->Count(); + $iTotalAvailableTime = $iMaxDuration * $iMaxCronProcess; + $iTimeSlot = (int)($iTotalAvailableTime / max($iCount, 1)); CronLog::Debug("Planned duration = $iMaxDuration seconds"); + CronLog::Debug("Planned duration per task = $iTimeSlot seconds"); CronLog::Debug("Loop pause = $iCronSleep seconds"); ReSyncProcesses($bDebug); @@ -230,7 +242,7 @@ function CronExec($bDebug) CronLog::Debug($sDebugMessage); } $aRunTasks = []; - while ($aTasks != []) { + while (count($aTasks) > 0) { $oTask = array_shift($aTasks); $sTaskClass = $oTask->Get('class_name'); @@ -245,7 +257,7 @@ function CronExec($bDebug) $aRunTasks[] = $sTaskClass; // N°3219 for each process will use a specific CMDBChange object with a specific track info - // Any BackgroundProcess can overrides this as needed + // Any BackgroundProcess can override this as needed CMDBObject::SetCurrentChangeFromParams("Background task ($sTaskClass)"); // Run the task and record its next run time @@ -253,7 +265,9 @@ function CronExec($bDebug) CronLog::Debug(">> === ".$oNow->format('Y-m-d H:i:s').sprintf(" Start task:%-'=49s", ' '.$sTaskClass.' ')); try { - $sMessage = RunTask($oTask, $iTimeLimit); + // The limit of time for this task corresponds to the time slot allowed for every task + // but limited to the cron job time limit + $sMessage = RunTask($oTask, min($iTimeLimit, time() + $iTimeSlot)); } catch (MySQLHasGoneAwayException $e) { CronLog::Error("ERROR : 'MySQL has gone away' thrown when processing $sTaskClass (error_code=".$e->getCode().")"); @@ -523,7 +537,7 @@ try else { // Limit the number of cron process to run in parallel - $iMaxCronProcess = MetaModel::GetConfig()->Get('cron.max_processes'); + $iMaxCronProcess = max(MetaModel::GetConfig()->Get('cron.max_processes'), 1); $bCanRun = false; $iProcessNumber = 0; for ($i = 0; $i < $iMaxCronProcess; $i++) {