diff options
| author | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
|---|---|---|
| committer | Philipp Schüttlöffel <schuettloeffel@zqs.uni-hannover.de> | 2024-09-24 10:53:31 +0200 |
| commit | 4459dd7917f4d1c34f40bb68f0e991e9c3d53e4c (patch) | |
| tree | 5c07151ae61276d334e88f6309c30d439a85c12e /lib/classes/CronjobScheduler.class.php | |
| parent | da0022e5c1abbf9825ae76debaabdff7e8623bb4 (diff) | |
| parent | 97a188592c679890a25c37ab78463add76a52ff7 (diff) | |
Merge branch 'main' into issue-3911issue-3911
Diffstat (limited to 'lib/classes/CronjobScheduler.class.php')
| -rw-r--r-- | lib/classes/CronjobScheduler.class.php | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/lib/classes/CronjobScheduler.class.php b/lib/classes/CronjobScheduler.class.php deleted file mode 100644 index 67db94c..0000000 --- a/lib/classes/CronjobScheduler.class.php +++ /dev/null @@ -1,344 +0,0 @@ -<?php -/** - * CronjobScheduler - Scheduler for the cronjobs. - * - * @author Jan-Hendrik Willms <tleilax+studip@gmail.com> - * @license http://www.gnu.org/licenses/gpl-2.0.html GPL version 2 - * @category Stud.IP - * @since 2.4 - */ - -// +---------------------------------------------------------------------------+ -// This file is part of Stud.IP -// CronjobScheduler.class.php -// -// Copyright (C) 2013 Jan-Hendrik Willms <tleilax+studip@gmail.com> -// +---------------------------------------------------------------------------+ -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or any later version. -// +---------------------------------------------------------------------------+ -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -// +---------------------------------------------------------------------------+ - -class CronjobScheduler -{ - protected static $instance = null; - - /** - * Returns the scheduler object. Implements the singleton pattern to - * ensure that only one scheduler exists. - * - * @return CronjobScheduler The scheduler object - */ - public static function getInstance() - { - if (self::$instance === null) { - self::$instance = new self(); - } - return self::$instance; - } - - /** - * Private constructor to ensure the singleton pattern is used correctly. - */ - private function __construct() - { - } - - /** - * Registers a new executable task. - * - * @param mixed $task Either path of the task class filename (relative - * to Stud.IP root) or an instance of CronJob - * @param bool $active Indicates whether the task should be set active - * or not - * @return String Id of the created task - * @throws InvalidArgumentException when the task class file does not - * exist - * @throws RuntimeException when task has already been registered - */ - public function registerTask($task, $active = true) - { - if (is_object($task)) { - $reflection = new ReflectionClass($task); - $class = $reflection->getName(); - $class_filename = studip_relative_path($reflection->getFileName()); - } else { - $filename = $GLOBALS['STUDIP_BASE_PATH'] . '/' . $task; - if (!file_exists($filename)) { - $message = sprintf('Task class file "%s" does not exist.', $task); - throw new InvalidArgumentException($message); - } - $class_filename = $task; - - $classes = get_declared_classes(); - require_once $filename; - $new_classes = array_diff(get_declared_classes(), $classes); - $new_classes = array_filter($new_classes, function ($class) { - return is_subclass_of($class, 'CronJob', true); - }); - $class = end($new_classes); - - if (empty($class)) { - throw new RuntimeException('No valid class was defined in file.'); - } - - $reflection = new ReflectionClass($class); - } - - if (!$reflection->isSubclassOf('CronJob')) { - $message = sprintf('Job class "%s" (defined in %s) does not extend the abstract CronJob class.', $class, $filename); - throw new RuntimeException($message); - } - - if ($task = CronjobTask::findOneByClass($class)) { - return $task->task_id; - } - - $task = new CronjobTask(); - $task->filename = $class_filename; - $task->class = $class; - $task->active = (int)$active; - $task->store(); - - return $task->task_id; - } - - /** - * Unregisters a previously registered task. - * - * @param String $task_id Id of the task to be unregistered - * @return CronjobScheduler to allow chaining - * @throws InvalidArgumentException when no task with the given id exists - */ - public function unregisterTask($task_id) - { - $task = CronjobTask::find($task_id); - if ($task === null) { - $message = sprintf('A task with the id "%s" does not exist.', $task_id); - throw new InvalidArgumentException($message); - } - $task->delete(); - - return $this; - } - - /** - * Schedules a task for a single execution at the provided time. - * - * @param String $task_id The id of the task to be executed - * @param int $timestamp When the task should be executed - * @param String $priority Priority of the execution (low, normal, high), - * defaults to normal - * @param Array $parameters Optional parameters passed to the task - * @return CronjobSchedule The generated schedule object. - */ - public function scheduleOnce($task_id, $timestamp, $priority = CronjobSchedule::PRIORITY_NORMAL, - $parameters = []) - { - $schedule = new CronjobSchedule(); - $schedule->type = 'once'; - $schedule->task_id = $task_id; - $schedule->parameters = $parameters; - $schedule->priority = $priority; - $schedule->next_execution = $timestamp; - - $schedule->store(); - - $task = $schedule->task; - $task->assigned_count += 1; - $task->store(); - - return $schedule; - } - - /** - * Schedules a task for periodic execution with the provided schedule. - * - * @param String $task_id The id of the task to be executed - * @param mixed $minute Minute part of the schedule: - * - null for "every minute" a.k.a. "don't care" - * - x < 0 for "every x minutes" - * - x >= 0 for "only at minute x" - * @param mixed $hour Hour part of the schedule: - * - null for "every hour" a.k.a. "don't care" - * - x < 0 for "every x hours" - * - x >= 0 for "only at hour x" - * @param mixed $day Day part of the schedule: - * - null for "every day" a.k.a. "don't care" - * - x < 0 for "every x days" - * - x > 0 for "only at day x" - * @param mixed $month Month part of the schedule: - * - null for "every month" a.k.a. "don't care" - * - x < 0 for "every x months" - * - x > 0 for "only at month x" - * @param mixed $day_of_week Day of week part of the schedule: - * - null for "every day" a.k.a. "don't care" - * - 1 >= x >= 7 for "exactly at day of week x" - * (x starts with monday at 1 and ends with - * sunday at 7) - * @param String $priority Priority of the execution (low, normal, high), - * defaults to normal - * @param Array $parameters Optional parameters passed to the task - * @return CronjobSchedule The generated schedule object. - */ - public function schedulePeriodic($task_id, $minute = null, $hour = null, - $day = null, $month = null, $day_of_week = null, - $priority = CronjobSchedule::PRIORITY_NORMAL, - $parameters = []) - { - $schedule = new CronjobSchedule(); - $schedule->type = 'periodic'; - $schedule->task_id = $task_id; - $schedule->parameters = $parameters; - $schedule->priority = $priority; - - $schedule->minute = $minute; - $schedule->hour = $hour; - $schedule->day = $day; - $schedule->month = $month; - $schedule->day_of_week = $day_of_week; - - $schedule->store(); - - $task = $schedule->task; - $task->assigned_count += 1; - $task->store(); - - return $schedule; - } - - /** - * Cancels the provided schedule. - * - * @param String $schedule_id Id of the schedule to be canceled - */ - public function cancel($schedule_id) - { - CronjobSchedule::find($schedule_id)->delete(); - } - - /** - * Cancels all schedules of the provided task. - * - * @param String $task_id Id of the task which schedules shall be canceled - */ - public function cancelByTask($task_id) - { - $schedules = CronjobSchedule::findByTask_id($task_id); - foreach ($schedules as $schedule) { - $schedule->delete(); - } - } - - /** - * Executes the available schedules if they are to be executed. - * This method can only be run once - even if one execution takes more - * than planned. This is ensured by a locking mechanism. - */ - public function run() - { - if (!Config::get()->CRONJOBS_ENABLE) { - return; - } - - $lock = new FileLock('studip-cronjob'); - - // Check whether a previous cronjob worker is still running. - if (!$lock->tryLock()) { - return; - } - - // Find all schedules that are due to execute and which task is active - $temp = CronjobSchedule::findBySQL('active = 1 AND next_execution <= UNIX_TIMESTAMP() ' - .'ORDER BY priority DESC, next_execution ASC'); - $schedules = array_filter($temp, function ($schedule) { return $schedule->task->active; }); - - if (count($schedules) === 0) { - return; - } - - foreach ($schedules as $schedule) { - try { - // Skip schedules with missing task classes - if (!$schedule->task->valid) { - throw new Exception(_('Die Klasse für den Cronjob-Task konnte nicht gefunden werden')); - } - - $log = new CronjobLog(); - $log->schedule_id = $schedule->schedule_id; - $log->scheduled = $schedule->next_execution; - $log->executed = time(); - $log->exception = null; - $log->duration = -1; - $log->store(); - - // Start capturing output and measuring duration - ob_start(); - $start_time = microtime(true); - - $schedule->execute(); - - // Actually capture output and duration - $end_time = microtime(true); - $output = ob_get_clean(); - - // Complete log - $log->output = $output; - $log->duration = $end_time - $start_time; - $log->store(); - } catch (Exception $e) { - $log->exception = $e; - - // Deactivate schedule - $schedule->deactivate(); - - // Send mail to root accounts - $subject = sprintf('[Cronjobs] %s: %s', - _('Fehlerhafte Ausführung'), - $schedule->title); - - $message = sprintf(_('Der Cronjob "%s" wurde deaktiviert, da bei der Ausführung ein Fehler aufgetreten ist.'), $schedule->title) . "\n"; - $message .= "\n"; - $message .= display_exception($e) . "\n"; - - $message .= _('Für weiterführende Informationen klicken Sie bitten den folgenden Link:') . "\n"; - - $old = URLHelper::setBaseURL($GLOBALS['ABSOLUTE_URI_STUDIP']); - $message .= URLHelper::getURL('dispatch.php/admin/cronjobs/logs/schedule/' . $schedule->schedule_id); - URLHelper::setBaseURL($old); - - $this->sendMailToRoots($subject, $message); - } - } - - // Release lock - $lock->release(); - } - - /** - * Sends an internal mail with the provided subject and message to all - * users with a global permission of "root". - * - * @param String $subject The subject of the message - * @param String $message The message itself - */ - private function sendMailToRoots($subject, $message) - { - $temp = User::findByPerms('root'); - $roots = SimpleORMapCollection::createFromArray($temp) - ->filter(function($r) { return $r->locked == 0; }) - ->pluck('username'); - - $msging = new messaging; - $msging->insert_message($message, $roots, '____%system%____', null, null, null, null, $subject, false, 'high'); - } -} |
