diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 7f06c122af..65772f0786 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -21,6 +21,7 @@ namespace Friendica\Core; +use Friendica\Core\Cache\Enum\Duration; use Friendica\Core\Worker\Entity\Process; use Friendica\Database\DBA; use Friendica\DI; @@ -54,7 +55,8 @@ class Worker const FAST_COMMANDS = ['APDelivery', 'Delivery']; const LOCK_PROCESS = 'worker_process'; - const LOCK_WORKER = 'worker'; + const LOCK_WORKER = 'worker'; + const LAST_CHECK = 'worker::check'; private static $up_start; private static $db_duration = 0; @@ -832,6 +834,17 @@ class Worker } else { self::spawnWorker(); } + } elseif (($active > $queues) && ($active < $maxqueues) && ($load < $maxsysload)) { + $max_idletime = DI::config()->get('system', 'worker_max_idletime'); + $last_check = DI::cache()->get(self::LAST_CHECK); + $last_date = $last_check ? date('c', $last_check) : ''; + if (($max_idletime > 0) && (time() > $last_check + $max_idletime) && !DBA::exists('workerqueue', ["`done` AND `executed` > ?", DateTimeFormat::utc('now - ' . $max_idletime . ' second')])) { + DI::cache()->set(self::LAST_CHECK, time(), Duration::HOUR); + Logger::info('The last worker execution had been too long ago.', ['last' => $last_check, 'last-check' => $last_date, 'seconds' => $max_idletime, 'load' => $load, 'max_load' => $maxsysload, 'active_worker' => $active, 'max_worker' => $maxqueues]); + return false; + } elseif ($max_idletime > 0) { + Logger::debug('Maximum idletime not reached.', ['last' => $last_check, 'last-check' => $last_date, 'seconds' => $max_idletime, 'load' => $load, 'max_load' => $maxsysload, 'active_worker' => $active, 'max_worker' => $maxqueues]); + } } } diff --git a/static/defaults.config.php b/static/defaults.config.php index 7c17dce227..431d5770d3 100644 --- a/static/defaults.config.php +++ b/static/defaults.config.php @@ -600,6 +600,10 @@ return [ Friendica\Core\Worker::PRIORITY_NEGLIGIBLE => 720 ], + // worker_max_idletime (Integer) + // Higly experimental! Maximum number of seconds after the last worker execution to enforce a new worker process. + 'worker_max_idletime' => 0, + // worker_processes_cooldown (Integer) // Maximum number per processes that causes a cooldown before each worker function call. 'worker_processes_cooldown' => 0,