phpBB

Development Wiki

PhpBB3.1/RFC/Modular cron

From phpBB Development Wiki

< PhpBB3.1‎ | RFC

Ticket: http://tracker.phpbb.com/browse/PHPBB3-9596

Description

The new cron architecture moves cron tasks into separate files, each task being represented by a single class. It is now possible to enable "System cron", which allows you to set up a true cron job instead of having users trigger cron tasks.

Motivation

The olympus implementation is severely limited, as it requires several file modifications to add new tasks. By making everything more modular, adding new cron tasks is as easy as dropping a file in a folder. This gives MOD writers the opportunity to handle parts of their MOD asynchronously and periodically. This makes the user experience better, because you can offload slow tasks to a background process.

Usage

Create a task

A cron task must implement the phpbb_cron_task interface. The phpbb_cron_task_base class is an abstract class that provides some sensible defaults for the methods defined by the interface. To have tasks automatically loaded, they must be placed in includes/cron/task/<namespace>/<task>.php, and use the class name phpbb_cron_task_<namespace>_<task>. The included cron tasks use the namespace 'core'.

An example cron for periodically backing up the database could look like this. The filename is includes/cron/task/backuper/backup.php.

class phpbb_cron_task_backuper_backup extends phpbb_cron_task_base
{
    public function 
run()
    {
        
do_backup();
        
set_config('last_backup_run'time());
    }
    
    public function 
should_run()
    {
        global 
$config;
        return 
$config['last_backup_run'] < time() - $config['backup_interval_config'];
    }
}

This class uses two config variables. last_backup_run specifies the time the last backup took place. backup_interval_config is the interval in which the task should run, in seconds, which the admin could set via the ACP. If the value is 60, it will run every minute.

Create a parametrized task

It is possible to pass parameters to a cron task, which are passed to cron.php when invoking it through the board footer. It is not possible to pass these parameters when using the system cron. For this reason you need to either need to make it non-runnable when system cron is enabled (you can define an is_runnable() method) or provide some default values for the parameters. Basically, those tasks will not work properly when using the system cron. For this reason you may want to provide system-cron compatible fallbacks (eg. prune_all_forums).

Parametrized tasks must implement the phpbb_cron_task_parametrized interface, which in addition to phpbb_cron_task interface adds get_parameters() and a parse_parameters(phpbb_request_interface $request) methods.

An example for where these are used is the prune_forum core task. The f parameter is passed into it, allowing the task to prune a specific forum. First it is instantiated in viewforum.php, passing the forum information into the constructor. Then get_parameters() is used to generate the URL for cron.php. When cron.php is actually requested with those parameters, they are fetched through parse_parameters().

You may have noticed that there is an is_runnable() and a should_run() method. is_runnable defines if the task is able to run at all, according to the board configuration. should_run checks if intervals have been met for the task to run.

One important difference with parametrized tasks is that you must set up the parameters yourself. To do this, call instantiate_task on the cron manager ($cron) with the name of the task and an argument. Here is the snippet from viewforum.php.

if (!$config['use_system_cron'])
{
    
$task $cron->instantiate_task('cron_task_core_prune_forum'$forum_data);
    if (
$task && $task->is_ready())
    {
        
$url $task->get_url();
        
$template->assign_var('RUN_CRON_TASK''<img src="' $url '" width="1" height="1" alt="cron" />');
    }
}

Take a look at the core tasks in includes/cron/task/core to get more of an idea of how the tasks work. Specifically the prune_forum task, as it is parametrized.

Install a task

Installing a task from a MOD is as easy as placing the files in includes/cron/task/<modname>. It will automatically be used.

Use system cron

In order to use the system cron you need to be able to set up cron jobs on your server. Note that cron is a Unix utility that schedules tasks to run at periodic intervals, so this discussion assumes that your forum is hosted on a Linux or Unix operating system where cron should be supported. If you have Windows hosting, similar functionality exists, but it is not called cron. On Windows this functionality is usually referred to as scheduled tasks. Consequently on Windows you will need to use a different interface, deal with a different terminology and different way of formatting paths. (Windows uses \ to delineate paths.)

First of all, enable the 'Run periodic tasks from system cron' setting in the 'Server settings' tab of the ACP.

Now you need to set up a periodic cron job. This depends on your system, but you usually have to edit /etc/crontab and add a job that runs every minute in the following format.

* * * * * cd "/path/to/board"; ./bin/phpbbcli.php cron:run

Note: The 'cd' is needed because all paths within phpBB are relative.

In shared hosting environments cron may be allowed but multiple commands may not be allowed in the cron. You may be able to use curl or wget instead of a system cron. Using this approach do NOT select 'Run periodic tasks from system cron' setting in the 'Server settings' tab of the ACP. You will still need to create a cron, however. The purpose of the cron is to trigger phpBB's cron regularly so if there is no board traffic programmed phpBB crons are still executed. A cron command similar to the following may work:

* * * * * curl -A=Mozilla/4.0 http://www.yourforum.com/forum/cron.php?cron_type=cron.task.cron_task

With this approach some trial and error may be necessary. Have the results of the cron sent to an email address that you can read and examine it for troubleshooting. It may be necessary to use a different user agent or to prepend curl or wget with the path, which might be /usr/bin or /bin. Your web host can provide information on the paths needed if necessary. When it is all working you may want to turn off the cron notifications.

Implementation

Most of the new code is in includes/cron, with changes to the core being minimal, except for cron.php. There are two interfaces: phpbb_cron_task and phpbb_cron_task_parametrized. The class loader is used extensively.

Notes