summaryrefslogtreecommitdiffstats
path: root/apis/cron.inc.php
blob: 30d6d45278ae0391f5f918c9f60da5a5079c1986 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php

/*
 * cronjob callback. This script does periodic checks, logging,
 * housekeeping etc. Should be called every 5 mins by cron.
 * Make a crontab entry that runs this as the same user the
 * www-php is normally run as, eg. */
// */5 *   * * *   www-data   php /path/to/api.php cron

if (!isLocalExecution())
	exit(0);

define('CRON_KEY_STATUS', 'cron.key.status');

function getJobStatus($id)
{
	// Re fetch from D on every call as some jobs could take longer
	// and we don't want to work with stale data
	$activeList = Property::getList(CRON_KEY_STATUS);
	foreach ($activeList as $item) {
		$entry = explode('|', $item, 2);
		if (count($entry) !== 2 || $id !== $entry[0])
			continue;
		return array('start' => $entry[1], 'string' => $item);
	}
	return false;
}

// Hooks by other modules
function handleModule($file)
{
	include_once $file;
}

foreach (glob('modules/*/hooks/cron.inc.php', GLOB_NOSORT) as $file) {
	preg_match('#^modules/([^/]+)/#', $file, $out);
	$mod = Module::get($out[1]);
	if ($mod === false)
		continue;
	$id = $mod->getIdentifier();
	// Check if job is still running, or should be considered crashed
	$status = getJobStatus($id);
	if ($status !== false) {
		$runtime = (time() - $status['start']);
		if ($runtime < 0) {
			// Clock skew
			Property::removeFromList(CRON_KEY_STATUS, $status['string']);
		} elseif ($runtime < 900) {
			// Allow up to 15 minutes for a job to complete before we complain...
			continue;
		} else {
			// Consider job crashed
			Property::removeFromList(CRON_KEY_STATUS, $status['string']);
			EventLog::failure('Cronjob for module ' . $id . ' seems to be stuck or has crashed. Check the php or web server error log.');
			continue;
		}
	}
	$now = time();
	Property::addToList(CRON_KEY_STATUS, "$id|$now", 1800);
	$mod->activate();
	handleModule($file);
	Property::removeFromList(CRON_KEY_STATUS, "$id|$now");
}