38 $this->logger->info(
"CRON - batch start");
41 $this->
settings->set(
"last_cronjob_start_ts", $ts);
46 $this->logger->info(sprintf(
47 'Verification of last run datetime (read from database): %s',
55 if (!defined(
"ILIAS_HTTP_PATH")) {
60 foreach (self::getCronJobData(null,
false) as $row) {
61 $job = self::getJobInstanceById($row[
"job_id"]);
69 foreach (self::getPluginJobs(
true) as $item) {
71 self::runJob($item[0]);
74 $this->logger->info(
"CRON - batch end");
87 $ilLog = $DIC->logger()->root();
91 $ilLog->write(
"CRON - manual start (" . $a_job_id .
")");
93 $job = self::getJobInstanceById($a_job_id);
95 if ($job->isManuallyExecutable()) {
96 $result = self::runJob($job, null,
true);
98 $ilLog->write(
"CRON - job " . $a_job_id .
" is not intended to be executed manually");
101 $ilLog->write(
"CRON - job " . $a_job_id .
" seems invalid or is inactive");
104 $ilLog->write(
"CRON - manual end (" . $a_job_id .
")");
117 protected static function runJob(
ilCronJob $a_job, array $a_job_data = null, $a_manual =
false)
121 $ilLog = $DIC->logger()->root();
122 $ilDB = $DIC->database();
126 include_once
"Services/Cron/classes/class.ilCronJobResult.php";
128 if ($a_job_data === null) {
130 $jobData = self::getCronJobData($a_job->
getId());
131 $a_job_data = array_pop($jobData);
135 if ($a_job_data[
"alive_ts"]) {
136 $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] .
" still running");
141 if (time() - $a_job_data[
"alive_ts"] > $cut) {
142 $ilDB->manipulate(
"UPDATE cron_job SET" .
143 " running_ts = " .
$ilDB->quote(0,
"integer") .
144 " , alive_ts = " .
$ilDB->quote(0,
"integer") .
145 " WHERE job_id = " .
$ilDB->quote($a_job_data[
"job_id"],
"text"));
147 self::deactivateJob($a_job);
152 $result->setMessage(
"Cron job deactivated because it has been inactive for 3 hours");
155 self::sendNotification($a_job,
$result);
158 self::updateJobResult($a_job,
$result, $a_manual);
160 $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] .
" deactivated (assumed crash)");
165 $a_job_data[
"job_result_ts"],
166 $a_job_data[
"schedule_type"],
167 $a_job_data[
"schedule_value"],
170 $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] .
" started");
172 $ilDB->manipulate(
"UPDATE cron_job SET" .
173 " running_ts = " .
$ilDB->quote(time(),
"integer") .
174 " , alive_ts = " .
$ilDB->quote(time(),
"integer") .
175 " WHERE job_id = " .
$ilDB->quote($a_job_data[
"job_id"],
"text"));
177 $ts_in = self::getMicrotime();
181 $result = new \ilCronJobResult();
183 $result->setMessage(sprintf(
"Exception: %s", $e->getMessage()));
185 $ilLog->error($e->getMessage());
186 $ilLog->error($e->getTraceAsString());
188 $result = new \ilCronJobResult();
190 $result->setMessage(sprintf(
"Exception: %s", $e->getMessage()));
192 $ilLog->error($e->getMessage());
193 $ilLog->error($e->getTraceAsString());
195 $ts_dur = self::getMicrotime() - $ts_in;
199 $result =
new ilCronJobResult();
202 $result->setMessage(
"Cron job did not return a proper result");
205 self::sendNotification($a_job,
$result);
208 $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] .
" no result");
212 self::deactivateJob($a_job);
215 self::sendNotification($a_job,
$result);
218 $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] .
" invalid configuration");
227 self::updateJobResult($a_job,
$result, $a_manual);
229 $ilDB->manipulate(
"UPDATE cron_job SET" .
230 " running_ts = " .
$ilDB->quote(0,
"integer") .
231 " , alive_ts = " .
$ilDB->quote(0,
"integer") .
232 " WHERE job_id = " .
$ilDB->quote($a_job_data[
"job_id"],
"text"));
234 $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] .
" finished");
236 $ilLog->write(
"CRON - job " . $a_job_data[
"job_id"] .
" returned status inactive");
252 $ilLog = $DIC->logger()->root();
253 $ilPluginAdmin = $DIC[
'ilPluginAdmin'];
256 if (substr($a_job_id, 0, 4) ==
"pl__") {
257 $parts = explode(
"__", $a_job_id);
258 $pl_name = $parts[1];
260 if ($ilPluginAdmin->isActive(
IL_COMP_SERVICE,
"Cron",
"crnhk", $pl_name)) {
261 $plugin_obj = $ilPluginAdmin->getPluginObject(
267 $job = $plugin_obj->getCronJobInstance($job_id);
282 $job_data = self::getCronJobData($a_job_id);
283 $job_data = array_pop($job_data);
284 if ($job_data[
"job_id"] == $a_job_id) {
285 return self::getJobInstance(
287 $job_data[
"component"],
294 $ilLog->write(
"CRON - job " . $a_job_id .
" seems invalid or is inactive");
305 public static function getJobInstance($a_id, $a_component, $a_class, $a_path = null)
309 $ilLog = $DIC->logger()->root();
312 $a_path = $a_component .
"/classes/";
314 $class_file = $a_path .
"class." . $a_class .
".php";
315 if (file_exists($class_file)) {
316 include_once $class_file;
317 if (class_exists($a_class)) {
318 $refl = new \ReflectionClass($a_class);
319 $job = $refl->newInstanceWithoutConstructor();
320 if ($refl->isSubclassOf(\ilCronJob::class)) {
321 if (0 === strlen($job->getId()) || !isset(
$_SERVER[
'PHP_SELF']) || basename(
$_SERVER[
'PHP_SELF']) !==
'setup.php') {
325 if ($job->getId() === $a_id) {
328 $mess .=
" - job id mismatch";
331 $mess .=
" - does not extend ilCronJob";
334 $mess =
"- class not found in file";
337 $mess =
" - class file not found";
340 $ilLog->write(
"Cron XML - Job " . $a_id .
" in class " . $a_class .
" (" .
341 $class_file .
") is invalid." . $mess);
359 $ilLog = $DIC->logger()->root();
360 $ilDB = $DIC->database();
362 if (!isset($DIC[
"ilSetting"])) {
363 $DIC[
"ilSetting"] =
function (
$c) {
371 $sql =
"SELECT job_id, schedule_type, component, class, path FROM cron_job" .
372 " WHERE job_id = " .
$ilDB->quote($a_job->
getId(),
"text");
373 $set =
$ilDB->query($sql);
374 $row =
$ilDB->fetchAssoc($set);
375 $job_id = $row[
'job_id'] ?? null;
376 $job_exists = ($job_id == $a_job->
getId());
377 $schedule_type = $row[
"schedule_type"] ?? null;
380 $row[
'component'] != $a_component ||
381 $row[
'class'] != $a_class ||
382 $row[
'path'] != $a_path
385 'UPDATE cron_job SET component = %s, class = %s, path = %s WHERE job_id = %s',
386 [
'text',
'text',
'text',
'text'],
387 [$a_component, $a_class, $a_path, $a_job->
getId()]
393 $sql =
"INSERT INTO cron_job (job_id, component, class, path)" .
394 " VALUES (" .
$ilDB->quote($a_job->
getId(),
"text") .
", " .
395 $ilDB->quote($a_component,
"text") .
", " .
396 $ilDB->quote($a_class,
"text") .
", " .
397 $ilDB->quote($a_path,
"text") .
")";
398 $ilDB->manipulate($sql);
400 $ilLog->write(
"Cron XML - Job " . $a_job->
getId() .
" in class " . $a_class .
404 self::updateJobSchedule(
412 include_once
"Services/Administration/classes/class.ilSetting.php";
417 self::activateJob($a_job);
425 self::updateJobSchedule(
433 self::updateJobSchedule($a_job, null, null);
445 public static function updateFromXML($a_component, $a_id, $a_class, $a_path = null)
449 $ilDB = $DIC->database();
451 if (!
$ilDB->tableExists(
"cron_job")) {
456 $job = self::getJobInstance($a_id, $a_component, $a_class, $a_path);
458 self::createDefaultEntry($job, $a_component, $a_class, $a_path);
468 public static function clearFromXML($a_component, array $a_xml_job_ids)
472 $ilDB = $DIC->database();
473 $ilLog = $DIC->logger()->root();
475 if (!
$ilDB->tableExists(
"cron_job")) {
481 $sql =
"SELECT job_id FROM cron_job" .
482 " WHERE component = " .
$ilDB->quote($a_component,
"text");
483 $set =
$ilDB->query($sql);
484 while ($row =
$ilDB->fetchAssoc($set)) {
485 $all_jobs[] = $row[
"job_id"];
488 if (
sizeof($all_jobs)) {
489 if (
sizeof($a_xml_job_ids)) {
491 foreach ($all_jobs as $job_id) {
492 if (!in_array($job_id, $a_xml_job_ids)) {
493 $ilDB->manipulate(
"DELETE FROM cron_job" .
494 " WHERE component = " .
$ilDB->quote($a_component,
"text") .
495 " AND job_id = " .
$ilDB->quote($job_id,
"text"));
497 $ilLog->write(
"Cron XML - Job " . $job_id .
" in class " . $a_component .
502 $ilDB->manipulate(
"DELETE FROM cron_job" .
503 " WHERE component = " .
$ilDB->quote($a_component,
"text"));
505 $ilLog->write(
"Cron XML - All jobs deleted for " . $a_component .
" as component is inactive.");
514 $ilPluginAdmin = $DIC[
'ilPluginAdmin'];
518 foreach ($ilPluginAdmin->getActivePluginsForSlot(
IL_COMP_SERVICE,
"Cron",
"crnhk") as $pl_name) {
519 $plugin_obj = $ilPluginAdmin->getPluginObject(
IL_COMP_SERVICE,
"Cron",
"crnhk", $pl_name);
521 foreach ((array) $plugin_obj->getCronJobInstances() as $job) {
523 $item = array_pop($jobData);
524 if (!is_array($item) || 0 === count($item)) {
530 $item = array_pop($jobData);
533 if (!$a_only_active ||
534 $item[
"job_status"] == 1) {
535 $res[$job->getId()] = array($job, $item);
553 $ilDB = $DIC->database();
557 if ($a_id && !is_array($a_id)) {
558 $a_id = array($a_id);
561 $sql =
"SELECT * FROM cron_job";
565 $where[] =
$ilDB->in(
"job_id", $a_id,
"",
"text");
569 if (!$a_include_inactive) {
570 $where[] =
"job_status = " .
$ilDB->quote(1,
"integer");
572 if (
sizeof($where)) {
573 $sql .=
" WHERE " . implode(
" AND ", $where);
577 $sql .=
" ORDER BY job_id";
579 $set =
$ilDB->query($sql);
580 while ($row =
$ilDB->fetchAssoc($set)) {
595 $ilDB = $DIC->database();
597 include_once
"Services/Cron/classes/class.ilCronJobResult.php";
601 $result->setMessage(
"Cron job re-activated by admin");
602 self::updateJobResult($a_job,
$result,
true);
604 $ilDB->manipulate(
"UPDATE cron_job" .
605 " SET running_ts = " .
$ilDB->quote(0,
"integer") .
606 " , alive_ts = " .
$ilDB->quote(0,
"integer") .
607 " , job_result_ts = " .
$ilDB->quote(0,
"integer") .
608 " WHERE job_id = " .
$ilDB->quote($a_job->
getId(),
"text"));
610 self::activateJob($a_job,
true);
622 $ilDB = $DIC->database();
625 if ($DIC->isDependencyAvailable(
'user')) {
626 $user = $DIC->user();
627 $user_id = $a_manual ? $user->getId() : 0;
630 $sql =
"UPDATE cron_job SET " .
631 " job_status = " .
$ilDB->quote(1,
"integer") .
632 " , job_status_user_id = " .
$ilDB->quote($user_id,
"integer") .
633 " , job_status_type = " .
$ilDB->quote($a_manual,
"integer") .
634 " , job_status_ts = " .
$ilDB->quote(time(),
"integer") .
635 " WHERE job_id = " .
$ilDB->quote($a_job->
getId(),
"text");
636 $ilDB->manipulate($sql);
650 $ilDB = $DIC->database();
653 $user_id = $a_manual ?
$ilUser->getId() : 0;
655 $sql =
"UPDATE cron_job SET " .
656 " job_status = " .
$ilDB->quote(0,
"integer") .
657 " , job_status_user_id = " .
$ilDB->quote($user_id,
"integer") .
658 " , job_status_type = " .
$ilDB->quote($a_manual,
"integer") .
659 " , job_status_ts = " .
$ilDB->quote(time(),
"integer") .
660 " WHERE job_id = " .
$ilDB->quote($a_job->
getId(),
"text");
661 $ilDB->manipulate($sql);
674 $job = self::getCronJobData($a_job_id);
675 if ((
bool) $job[0][
"job_status"]) {
689 $job = self::getCronJobData($a_job_id);
690 if (!(
bool) $job[0][
"job_status"]) {
706 $ilDB = $DIC->database();
709 $user_id = $a_manual ?
$ilUser->getId() : 0;
711 $sql =
"UPDATE cron_job SET " .
712 " job_result_status = " .
$ilDB->quote($a_result->
getStatus(),
"integer") .
713 " , job_result_user_id = " .
$ilDB->quote($user_id,
"integer") .
714 " , job_result_code = " .
$ilDB->quote($a_result->
getCode(),
"text") .
715 " , job_result_message = " .
$ilDB->quote($a_result->
getMessage(),
"text") .
716 " , job_result_type = " .
$ilDB->quote($a_manual,
"integer") .
717 " , job_result_ts = " .
$ilDB->quote(time(),
"integer") .
718 " , job_result_dur = " .
$ilDB->quote($a_result->
getDuration() * 1000,
"integer") .
719 " WHERE job_id = " .
$ilDB->quote($a_job->
getId(),
"text");
720 $ilDB->manipulate($sql);
733 $ilDB = $DIC->database();
735 if ($a_schedule_type === null ||
738 $sql =
"UPDATE cron_job SET " .
739 " schedule_type = " .
$ilDB->quote($a_schedule_type,
"integer") .
740 " , schedule_value = " .
$ilDB->quote($a_schedule_value,
"integer") .
741 " WHERE job_id = " .
$ilDB->quote($a_job->
getId(),
"text");
742 $ilDB->manipulate($sql);
753 list($usec, $sec) = explode(
" ", microtime());
754 return ((
float) $usec + (
float) $sec);
762 public static function ping($a_job_id)
765 $ilDB = $DIC->database();
767 $ilDB->manipulate(
"UPDATE cron_job SET " .
768 " alive_ts = " .
$ilDB->quote(time(),
"integer") .
769 " WHERE job_id = " .
$ilDB->quote($a_job_id,
"text"));
static getJobInstance($a_id, $a_component, $a_class, $a_path=null)
Get job instance (by job data)
static updateFromXML($a_component, $a_id, $a_class, $a_path=null)
Process data from module.xml/service.xml.
const CODE_SUPPOSED_CRASH
static sendNotification(ilCronJob $a_job, $a_message)
Send notification to admin about job event(s)
getValidScheduleTypes()
Returns a collection of all valid schedule types for a specific job.
const STATUS_INVALID_CONFIGURATION
runActiveJobs()
Run all active jobs.
Cron job application base class.
static deactivateJob(ilCronJob $a_job, $a_manual=false)
Deactivate cron job.
static runJob(ilCronJob $a_job, array $a_job_data=null, $a_manual=false)
Run single cron job (internal)
static activateJob(ilCronJob $a_job, $a_manual=false)
Activate cron job.
static isJobInactive($a_job_id)
Check if given job is currently inactive.
static setUseRelativeDates($a_status)
set use relative dates
static runJobManual($a_job_id)
Run single job manually.
activationWasToggled($a_currently_active)
Cron job status was changed.
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date public.
static useRelativeDates()
check if relative dates are used
static resetJob(ilCronJob $a_job)
Reset job.
static _lookupValue($a_module, $a_keyword)
static getCronJobData($a_id=null, $a_include_inactive=true)
Get cron job configuration/execution data.
foreach($_POST as $key=> $value) $res
static getJobInstanceById($a_job_id)
Get job instance (by job id)
hasFlexibleSchedule()
Can the schedule be configured?
static createDefaultEntry(ilCronJob $a_job, $a_component, $a_class, $a_path)
isActive($a_ts_last_run, $a_schedule_type, $a_schedule_value, $a_manual=false)
Is job currently active?
static updateJobResult(ilCronJob $a_job, ilCronJobResult $a_result, $a_manual=false)
Save job result.
getDefaultScheduleType()
Get schedule type.
static ping($a_job_id)
Keep cron job alive.
static getPluginJobs($a_only_active=false)
static getMicrotime()
Get current microtime.
static clearFromXML($a_component, array $a_xml_job_ids)
Clear job data.
getDefaultScheduleValue()
Get schedule value.
__construct(\ilSetting $settings, \ilLogger $logger)
ilCronManager constructor.
Class ilStrictCliCronManager.
static updateJobSchedule(ilCronJob $a_job, $a_schedule_type, $a_schedule_value)
Update job schedule.
Cron job result data container.
Component logger with individual log levels by component id.
static isJobActive($a_job_id)
Check if given job is currently active.
hasAutoActivation()
Is to be activated on "installation".