From c197aa8beb0cdcff81fa382a1b0e93c32bd6d43c Mon Sep 17 00:00:00 2001 From: Brook Gagnon Date: Thu, 12 Sep 2024 22:59:34 +0000 Subject: [PATCH] add cron monitor support (runs background processes more quickly as needed) --- .phpcs.xml.dist | 1 - classes/cron/extractthumbnails.php | 4 +- cron.php | 78 -------------------- tools/cli/commands/cron.php | 110 +++++++++++++++++++++++++++++ tools/cli/ob.php | 7 +- 5 files changed, 116 insertions(+), 84 deletions(-) delete mode 100644 cron.php create mode 100644 tools/cli/commands/cron.php diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist index e962eb59..782f9471 100644 --- a/.phpcs.xml.dist +++ b/.phpcs.xml.dist @@ -10,7 +10,6 @@ api.php components.php config.sample.php - cron.php index.php remote.php strings.php diff --git a/classes/cron/extractthumbnails.php b/classes/cron/extractthumbnails.php index fe0547cb..cf0df476 100644 --- a/classes/cron/extractthumbnails.php +++ b/classes/cron/extractthumbnails.php @@ -8,7 +8,7 @@ class ExtractThumbnails extends Cron { public function interval(): int { - return 60; + return 1; } public function run(): bool @@ -57,7 +57,7 @@ public function run(): bool } } - return false; + return true; } private function runVideo($item, $input_file, $output_file): bool diff --git a/cron.php b/cron.php deleted file mode 100644 index cb2bb868..00000000 --- a/cron.php +++ /dev/null @@ -1,78 +0,0 @@ -. -*/ - -require_once('components.php'); - -$lock = new OBFLock('core-cron'); -if (!$lock->acquire()) { - die('Unable to get cron lock. Already running?' . PHP_EOL); -} - -$db = OBFDB::get_instance(); - -// set cron last run -$db->where('name', 'cron_last_run'); -$cron_last_run = $db->get('settings'); -if (!$cron_last_run) { - $db->insert('settings', ['name' => 'cron_last_run', 'value' => time()]); -} else { - $db->where('name', 'cron_last_run'); - $db->update('settings', ['value' => time()]); -} - -// require cron files -// TODO add support for module cron classes (last run tracked in db as cron-modulename-classname). -$jobs = []; -require_once('classes/base/cron.php'); -foreach (glob('classes/cron/*.php') as $file) { - require_once($file); - $class = '\OB\Classes\Cron\\' . basename($file, '.php'); - $jobs[] = new $class(); -} - -// loop through jobs and check interval against last run. run if needed. -foreach ($jobs as $job) { - // reliable way to get the class name without namespace - $classReflection = new ReflectionClass($job); - $className = strtolower($classReflection->getShortName()); - - // get our last run time - $db->where('name', 'cron-core-' . $className); - $lastRun = $db->get_one('settings'); - $interval = $job->interval(); - - // if no last run time, or time to run again... - if (!$lastRun || $lastRun['value'] + $interval < time()) { - $status = $job->run(); - - // if successful, update last run time - if ($status) { - if ($lastRun) { - // has previous run, update time. - $db->where('name', 'cron-core-' . $className); - $db->update('settings', ['value' => time()]); - } else { - // first time running, insert time. - $db->insert('settings', ['name' => 'cron-core-' . $className, 'value' => time()]); - } - } - } -} diff --git a/tools/cli/commands/cron.php b/tools/cli/commands/cron.php new file mode 100644 index 00000000..e6ce77ee --- /dev/null +++ b/tools/cli/commands/cron.php @@ -0,0 +1,110 @@ + $job) { + // reliable way to get the class name without namespace + $classReflection = new \ReflectionClass($job); + $className = strtolower($classReflection->getShortName()); + + // get our last run time + $db->where('name', 'cron-core-' . $className); + $lastRun = $db->get_one('settings'); + + // if no last run time, set nextRun to zero + if (!$lastRun) { + $nextRun = 0; + } else { + $nextRun = $lastRun['value'] + $job->interval(); + } + $jobs_to_run[$index] = ['nextRun' => $nextRun, 'className' => $className]; +} + +$run_jobs = function () use ($jobs, &$jobs_to_run, $db, $lock) { + // loop through jobs and check interval against last run. run if needed. + foreach ($jobs_to_run as $index => $job_to_run) { + // if not time to run, skip + if ($job_to_run['nextRun'] > time()) { + continue; + } + + // aquire lock (or exit) + $lock_aquired = $lock->acquire(); + if (!$lock_aquired) { + echo 'Unable to get cron lock. Is another monitor or job already running?' . PHP_EOL; + exit(1); + } + + // get the job + $job = $jobs[$index]; + + // run job + $status = $job->run(); + + // if successful, update last run time for this job and main, as well as update our next run time locally + if ($status) { + // update last run time for this job + if ($job_to_run['nextRun'] > 0) { + // has previous run, update time. + $db->where('name', 'cron-core-' . $job_to_run['className']); + $db->update('settings', ['value' => time()]); + } else { + // first time running, insert time. + $db->insert('settings', ['name' => 'cron-core-' . $job_to_run['className'], 'value' => time()]); + } + + // update next run time in our local variable + $jobs_to_run[$index]['nextRun'] = time() + $job->interval(); + + // update our main cron_last_run time + $db->where('name', 'cron_last_run'); + $cron_last_run = $db->get_one('settings'); + if (!$cron_last_run) { + $db->insert('settings', ['name' => 'cron_last_run', 'value' => time()]); + } else { + $db->where('name', 'cron_last_run'); + $db->update('settings', ['value' => time()]); + } + + // update $jobs_to_run with next time + $jobs_to_run[$index]['nextRun'] = time() + $job->interval(); + } + + // release our lock + $lock->release(); + } +}; + +if ($subcommand === 'monitor') { + // monitor mode + echo 'cron monitor started' . PHP_EOL; + while (true) { + $run_jobs(); + sleep(1); + } +} else { + $run_jobs(); +} diff --git a/tools/cli/ob.php b/tools/cli/ob.php index ea073c21..2226ad96 100644 --- a/tools/cli/ob.php +++ b/tools/cli/ob.php @@ -64,7 +64,8 @@ public function help() echo Helpers::table(spacing: 5, rows: [ ['check', 'check installation for errors'], - ['cron run', 'run scheduled tasks'], + ['cron run', 'run scheduled tasks once'], + ['cron monitor', 'monitor and run cron tasks as needed'], ['updates list all', 'list all available updates'], ['updates list core', 'list core ob updates'], ['updates list module ', 'list updates for specified module'], @@ -83,8 +84,8 @@ public function check() public function cron() { global $subcommand; - if ($subcommand == 'run') { - require('cron.php'); + if ($subcommand == 'run' || $subcommand == 'monitor') { + require(__DIR__ . '/commands/cron.php'); } else { $this->help(); }