Task scheduling
Learn how to create scheduled tasks that can be run crontab-like, repeatedly or just once.
Setup
Before you begin, configure the operating system’s Task scheduling service to execute the required tasks.
Examples include cron (configured through crontab) on Unix-like systems,
Windows Task Scheduler on Windows, and launchd on macOS.
Enabling in Crontab
You can automatically configure Cron (if the system supports it) using the built-in command:
./run schedule:enable
Disabling in Crontab
./run schedule:disable
Manually configuring cron:
If the automated command is not supported by the environment, it is still possible to manually
add a similar instruction to the crontab (adjust the paths):
* * * * * /usr/bin/php /path/to/my-app/run schedule:run >> /path/to/my-app/storage/logs/schedule.log 2>&1
Manually configuring on Windows:
schtasks /Create /TN "Inphinit Schedule" /TR "cmd /c C:\php\php.exe \"C:/path/to/my-app/run\" schedule:run >> \"C:/path/to/my-app/system/storage/logs/schedule.log\" 2>&1" /SC MINUTE /MO 1 /F
Creating tasks
It is possible to schedule functions, existing commands, and shell commands.
To schedule a function, edit the system/console.php file and add tasks as in the examples:
use Inphinit\Experimental\Scheduling\Task;
$mytask = $scheduler->call('mytask1', function (Task $task) {
echo 'Hello World!';
});
// Defines a task to be executed every hour.
$mytask->interval(3600);
To schedule an existing command, follow the example:
// Creates the command `php run sample`, which can be executed in the terminal.
$mycommand = $console->action('sample', function (Command $command, array $options, array $residues) {
echo 'Hello World!';
});
// Schedules the command to be executed according to the next instruction.
$mytask = $scheduler->command('mytask2', $mycommand);
// Configures the schedule to run at the 10-minute mark.
$mytask->interval(600);
It is also possible to schedule arbitrary commands, for example, running VACUUM on Postgres databases at regular intervals:
// Sets the task to run on the 1st of every month at 03:00 AM (UTC).
$scheduler->shell('mytask3', 'vacuumdb -d my_database')->cron(0, 3, 1, '*', '*');
Another example using the systemd-tmpfiles program.
// Performs cleanup every day at 23:30 (UTC)
$scheduler->shell('mytask4', 'systemd-tmpfiles --clean')->at(23, 30);
Another example using the a NodeJS:
// Performs a JavaScript file using NodeJS every day at 00:00 (UTC)
$scheduler->shell('mynodetask', 'node /foo/bar/script.js')->at(0, 0);
Testing a task
To test a task, regardless of the schedule, simply run the command:
./run schedule:run --task mytask1
Configuring the schedule
When adding a task, it is necessary to configure the trigger time and whether execution should occur in the background using the following methods:
| Comando | Descrição |
|---|---|
cron($minute, $hour, $day, $month, $weekday) |
Schedule the task using crontab-like fields. |
interval(int $seconds) |
Schedule the task to run repeatedly at the specified interval in seconds, counting from its last execution. |
once(DateTime $datetime) |
Schedule the task to run exactly once at (or after) the specified date/time. Once executed, it will not run again. |
at(int $hour, int $minute) |
Shortcut to schedule the task for daily execution at a fixed time. Equivalent to cron($minute, $hour, '*', '*', '*'). |
runInBackground(bool $enable) |
Marks this task to be dispatched as an independent background process, rather than running synchronously within the scheduler process. |
Since most methods return the instance of the Inphinit\Experimental\Scheduling\Task class itself, it is possible to use them like this:
$scheduler->call('mytask5', function () { ... })
->cron(30, 16, 1, '*', '*')
->runInBackground(true);
Running in the background
Multiple tasks scheduled for the same time will be executed sequentially, based on the order in which they were defined.
Long-running tasks can cause subsequent tasks to start much later than expected.
To execute a long task without having to wait for it to start, you should use the runInBackground() method,
which allows for background execution. Example:
$scheduler->call('mytask6', function () { ... })->at(14, 30)->runInBackground(true);
$scheduler->call('mytask7', function () { ... })->at(14, 30)->runInBackground(true);
Tasks will continue to be executed in the order in which they were declared. This means that background tasks will also be invoked in that same order; if a non-background task precedes them, the background task will have to wait. To execute background tasks ahead of schedule, use:
$scheduler->prioritizeBackgroundTasks(true);
Changing timeZone
By default, all tasks are executed based on UTC, but it is possible to explicitly configure the once()
method to execute a task at a specific time:
use Inphinit\Experimental\Scheduling\Task;
$dt = new DateTime('2030-01-01', new DateTimeZone('America/New_York'));
// It will execute on 2030-01-01 at 12:00:00
$scheduler->call('mytask3', function (Task $task) {
echo 'Hello World!';
})->once($dt);
To set the time zone for all tasks, the method to use is $scheduler->setTimeZone() in system/console.php,
as shown in the example:
$time_zone = new DateTimeZone('America/New_York');
$scheduler->setTimeZone($time_zone);
// Runs every day at 10:00 AM New York time.
$scheduler->call('mytask1', function () { ... })->at(10, 0);
// Runs every day at 3:30 PM São Paulo time.
$scheduler->call('mytask2', function () { ... })->at(15, 30);
// Runs every day at 8:00 PM New York time.
$scheduler->call('mytask3', function () { ... })->at(20, 0);
Examples of usage
The ::cron() method is similar to the crontab structure, as can be seen in the examples:
$scheduler->call('mytask1', function () { ... })->cron($minute, $hour, $day, $month, $weekday);
Examples:
| Usage | Explanation |
|---|---|
cron('*', '*', '*', '*', '*') |
Runs every minute. The five fields are set to *, meaning any minute, any hour, any day of the month, any month, and any day of the week. |
cron('*/5', '*', '*', '*', '*') |
Runs every 5 minutes. */5 in the minute field means 0, 5, 10, 15, etc. |
cron(0, '*', '*', '*', '*') |
Runs at minute 0 of every hour—that is, once per hour. |
cron(30, 8, '*', '*', '*') |
Runs every day at 08:30. 30 represents the minute and 8 represents the hour. |
cron(0, 0, '*', '*', '*') |
Runs every day at midnight. 0 in the minute field and 0 in the hour field. |
cron(0, 12, '*', '*', 1) |
Runs every Monday at noon. 1 represents Monday in traditional cron implementations. |
cron(0, 9, '*', '*', '1-5') |
Runs from Monday to Friday at 09:00. 1-5 represents the range from Monday to Friday. |
cron(0, 18, '*', '*', '6,0') |
Runs on Saturdays and Sundays at 18:00. 6,0 represents Saturday and Sunday in cron syntax where Sunday is 0. |
cron(0, 0, 1, '*', '*') |
Runs on the first day of every month at midnight. The third field, 1, is the day of the month. |
cron(30, 7, 15, '*', '*') |
Runs on the 15th of every month at 07:30. |
cron(0, 10, '*', 1, '*') |
Runs every day in January at 10:00. 1 in the month field represents January. |
cron(0, 0, 1, 1, '*') |
Runs at midnight on January 1st. |
cron(15, 14, 1, '*', 5) |
Runs at 14:15 when it is the 1st and a Friday, subject to the specific cron implementation's semantics. |
cron(0, '*/2', '*', '*', '*') |
Runs every 2 hours, always at minute zero: 00:00, 02:00, 04:00, etc. |
cron('*/10', '9-17', '*', '*', '1-5') |
Runs every 10 minutes, between 09:00 and 17:59, Monday through Friday. |
cron(0, 0, '*', '*', 0) |
Runs every Sunday at midnight. 0 in the fifth field represents Sunday in traditional cron. |
cron(0, 0, '*', '*', '1,3,5') |
Runs at midnight on Mondays, Wednesdays, and Fridays. The comma allows you to specify multiple values. |
cron(0, 0, '1-7', '*', 1) |
Runs at midnight on Mondays that fall between the 1st and the 7th of the month. |
cron(0, 0, 1, '*/3', '*') |
Runs on the first day of every third month, at midnight. */3 in the month field represents three-month intervals. |
cron(30, 15, '*', '*', '*') |
Runs every day at 15:30. This is a simple example to visualize the minute (30) and hour (15) separately. |