Agendamento de tarefas
Aprenda como criar tarefas agendadas que podem ser executadas no estilo crontab, repetidamente ou apenas uma vez.
Configurando
Antes de começar, é necessário configurar o software de agendamento disponível no sistema operacional para executar as tarefas.
Se o ambiente usa crontab ou schtasks (Windows) é possivel executar o comando que faz a configuração automizada:
./run schedule:enable
Depois de configurado é possivel remover do crontab ou schtasks de forma automatizada executando:
./run schedule:enable
Configurando manualmente CRON:
Acaso o comando automizado não seja suportado pelo ambiente, ainda é possivel adicionar manualmente no crontab uma instrução semelhante (ajuste os caminhos):
* * * * * /usr/bin/php /path/to/my-app/run schedule:run >> /dev/null 2>&1
Configurando manualmente no Windows:
No Windows o sistema que pode ser usado é o Task Scheduler, via interface gráfica (o que pode ser mais intuitivo) ou via comando, similar a esse:
schtasks /create /tn "My Tasks" /tr "C:\php\php.exe C:\path\to\my-app\run schedule:run" /sc minute /mo 1 /f
Criando tarefas
É possivel agendar funções, comandos existentes, e comandos shell. Para agendar uma função use:
use Inphinit\Experimental\Scheduling\Task;
$mytask = $scheduler->call('mytask1', function (Task $task) {
echo 'Hello World!';
});
// Define para tarefa a ser executada a cada hora
$mytask->interval(3600);
Para agendar um comando existente faça como no exemplo:
// Cria o comando que pode ser executado no terminal `php run sample`
$mycommand = $console->action('sample', function (Command $command, array $options, array $residues) {
echo 'Hello World!';
});
// Agenda o comando para ser executado conforme a próxima instrução
$mytask = $scheduler->command('mytask2', $mycommand);
// Configura o agendamento para ser executado a 10 minutos
$mytask->interval(600);
Também é possivel agendar comandos arbitrários, com um exemplo para executar vacumm em bancos Postgres de tempos em tempos:
// Define para tarefa a ser executada no dia 1 de todos meses as 03:00 AM (UTC)
$scheduler->shell('vacuumdb -d my_database')->cron(0, 3, 1, '*', '*');
Outro exemplo usando o programa systemd-tmpfiles
// Executa limpeza todos dias as 23:30 (UTC)
$scheduler->shell('systemd-tmpfiles --clean')->at(23, 30);
Testando tarefa
Para testar uma tarefa, independente do agendamento, basta executar o comando:
./run schedule:run --task mytask1
Configurando o agendamento
Ao adicionar uma tarefa é necessário configurar o momento do disparo e se a execução deve ocorrer em background com os seguintes métodos:
| Comando | Descrição |
|---|---|
cron($minute, $hour, $day, $month, $weekday) |
Agende a tarefa usando campos no estilo crontab. |
interval(int $seconds) |
Agende a tarefa para ser executada repetidamente a cada intervalo de segundos especificado, contado a partir de sua última execução. |
once(string|DateTime $datetime) |
Agende a tarefa para ser executada exatamente uma vez, na data/hora especificada (ou após ela). Uma vez executada, ela não será mais realizada. |
at(int $hour, int $minute) |
Atalho para agendar a tarefa para execução diária em um horário fixo. Equivalente a cron($minute, $hour, '*', '*', '*'). |
runInBackground(bool $enable) |
Marca esta tarefa para ser despachada como um processo em segundo plano independente, em vez de ser executada de forma síncrona dentro do processo do agendador. |
Para experimentar, você pode usar funções, closures ou um controller dentro do namespace Tasks,
criando um arquivo como system/Tasks/Foo/Bar/BazTask.php e adicionando-o ao system/console.php como:
Como a maioria dos métodos retorna a própria instancia da classe Inphinit\Experimental\Scheduling\Task,
é possivel usando como:
$scheduler
->command('mytask', $mycommand)
->cron(30, 16, 1, '*', '*')
->runInBackground(true);
Rodando em background
Diversas tarefas agendadas para o mesmo horário serão executadas sequencialmente, com base na ordem em que foram definidas.
Tarefas de longa duração podem fazer com que as tarefas subsequentes iniciem muito mais tarde do que o esperado.
Para executar uma tarefa longa sem ter que esperar que ela inicie, você deve usar o método runInBackground(),
que permitirá execuções simuladas, por exemplo:
$scheduler->call(function () { ... })->at(14, 30)->runInBackground(true);
$scheduler->call(function () { ... })->at(14, 30)->runInBackground(true);
Alterando timeZone
Por padrão todas tarefas são executadas baseados em UTC, mas é possivel configurar o método once()
explicitamente para executar uma tarefa em uma hora especifica:
use Inphinit\Experimental\Scheduling\Task;
$time_zone = new DateTime('2030-01-01', new DateTimeZone('America/Sao_Paulo'));
// Executará em 2030-01-01 12:00:00
$scheduler->call('mytask3', function (Task $task) {
echo 'Hello World!';
})->once($time_zone);
Para definir timezone para todas tarefas o método a ser usado é $scheduler->setTimeZone()
no system/console.php, como no exemplo:
$time_zone = new DateTimeZone('America/Sao_Paulo');
$scheduler->setTimeZone($time_zone);
// Executará todos os dias as 10:00 AM do horário de São Paulo
$scheduler->call(function () { ... })->at(10, 0);
// Executará todos os dias as 15:30 do horário de São Paulo
$scheduler->call(function () { ... })->at(15, 30);
// Executará todos os dias as 20:00 do horário de São Paulo
$scheduler->call(function () { ... })->at(20, 0);