Actions

Developer Area/Cron API

From Mahara Wiki

< Developer Area
Revision as of 16:40, 21 January 2014 by Aaronw (talk | contribs) (Created page with "Mahara provides a '''Cron API''' to allow for scheduled tasks. It uses an internal table of schedules to determine how frequently the tasks run, and it uses a lock to prevent two…")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Mahara provides a Cron API to allow for scheduled tasks. It uses an internal table of schedules to determine how frequently the tasks run, and it uses a lock to prevent two instances of the same task from running at the same time.

How it works

Here's the underlying architecture of the Mahara cron job.

The One and Only cron script

All of Mahara's cron tasks are handled by one script, htdocs/lib/cron.php. This script is meant to be [System_Administrator%27s_Guide/Cron_Job|scheduled by the System Administrator] to be executed once per minute, either via the command-line or through an HTTP request.

It then checks a series of internal tables in Mahara to see which internal cron tasks need to be executed, and carries them out.

Note that the cron script sets the [Developer_Area/Pagetop_Constants|pagetop constant]] 'CRON', which allows for scripts to detect that they're being executed by the cron and to behave accordingly. For instance, some checks for a current logged-in user are ignored when CRON is defined.

The cron tables

The individual cron tasks that Mahara should execute, are stored in a series of tables in Mahara's database.

Cron tasks pertaining to Mahara core (as opposed to a plugin) are stored in the aptly named cron table. Its most important field is cron.callfunction, which holds the name of a PHP function that will be called to carry out that task. The other fields store scheduling information about how often it should run. The legal values for the scheduling section are essentially the same as those for the standard Unix crontab.

Each Mahara plugin type has its own separate cron table: blocktype_cron, artefact_cron, etc. These tables are much the same as the core cron table, except they additionally indicate the name of the plugin the task belongs to. The callfunction in these tables should be a static method of the plugin's main class.

Cron locks

In order to avoid concurrency problems, Mahara uses a system of cron locks to prevent multiple copies of the same cron task from running at the same time.

The system is quite simple. Before executing a task, Mahara looks for a lock record for that cron, in the database. Specifically, it checks for a config record called "_cron_lock_core_{$callfunction}" (for a core cron task) or "_cron_lock_{$plugintype}{$pluginname}_{$callfunction}" (for a plugin cron task). If it finds this, it knows that another copy of the cron task already claimed the lock and is executing, and so it skips that task and doesn't execute it. On the other hand, if it doesn't find a lock present, it sets the lock itself and begins executing the task. When it has finished the task, it deletes the lock record.

But what happens if the cron task crashes before it can delete the lock record? Well, the lock record is a config record with a particular name, but every config also has a value. In this case, the cron script sets the value to be the time the lock was claimed. Using that, we can tell how long a particular task has been running. Each time the cron job finds a lock already present, it checks the timestamp stored in its value, and if it's more than 24 hours old it assumes the lock belonged to a task that crashed, so it clears it and begins executing the task again.