Cron jobs

Some tasks must be executed regularly: refresh some materialized views, remove old data, …

For this purpose, one can programmatically implements a “cron job”, which will be scheduled by a specific command.

The command chill:cron-job:execute

The command chill:cron-job:execute will schedule a task, one by one. In a classical implementation, it should be executed every 15 minutes (more or less), to ensure that every task can be executed.

Warning

This command should not be executed in parallel. The installer should ensure that two job are executed concurrently.

How to implements a cron job ?

Implements a Chill\MainBundle\Cron\CronJobInterface. Here is an example:

namespace Chill\MainBundle\Service\Something;

use Chill\MainBundle\Cron\CronJobInterface;
use Chill\MainBundle\Entity\CronJobExecution;
use DateInterval;
use DateTimeImmutable;

class MyCronJob implements CronJobInterface
{
    public function canRun(?CronJobExecution $cronJobExecution): bool
    {
        // the parameter $cronJobExecution contains data about the last execution of the cronjob
        // if it is null, it should be executed immediatly
        if (null === $cronJobExecution) {
            return true;
        }

        if ($cronJobExecution->getKey() !== $this->getKey()) {
            throw new UnexpectedValueException();
        }

        // this cron job should be executed if the last execution is greater than one day, but only during the night

        $now = new DateTimeImmutable('now');

        return $cronJobExecution->getLastStart() < $now->sub(new DateInterval('P1D'))
            && in_array($now->format('H'), self::ACCEPTED_HOURS, true)
            // introduce a random component to ensure a roll of task execution when multiple instances are hosted on same machines
            && mt_rand(0, 5) === 0;
    }

    public function getKey(): string
    {
        return 'arbitrary-and-unique-key';
    }

    public function run(): void
    {
        // here, we execute the command
    }
}

How are cron job scheduled ?

If the command chill:cron-job:execute is run with one or more job argument, those jobs are run, without checking that the job can run (the method canRun is not executed).

If any job argument is given, the CronManager schedule job with those steps:

  • the tasks are ordered, with:
    • a priority is given for tasks that weren’t never executed;
    • then, the tasks are ordered, the last executed are the first in the list
  • then, for each tasks, and in the given order, the first task where canRun return TRUE will be executed.

The command chill:cron-job:execute execute only one task.