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, configure o serviço de Agendamento de tarefas do sistema operacional para executar as tarefas necessárias.
Exemplos incluem o cron (configurado via crontab) em sistemas do tipo Unix,
o Agendador de Tarefas do Windows no Windows e o launchd no macOS.
Habilitando em Crontab
Você pode configurar o Cron automaticamente (se o sistema oferecer suporte) usando o comando built-in:
./run schedule:enable
Desabilitando em Crontab
./run schedule:disable
Configurando o cron manualmente:
Se o comando automatizado não for suportado pelo ambiente, ainda é possível adicionar manualmente uma instrução semelhante
ao crontab (ajuste os caminhos):
* * * * * /usr/bin/php /path/to/my-app/run schedule:run >> /path/to/my-app/storage/logs/schedule.log 2>&1
Configurando manualmente em 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
Criando tarefas
É possivel agendar funções, comandos existentes, e comandos shell.
Para agendar uma função, edite o arquivo system/console.php
e adicione tarefas como nos exemplos:
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('mytask3', '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('mytask4', 'systemd-tmpfiles --clean')->at(23, 30);
Outro exemplo usando NodeJS:
// Executa um arquivo JavaScript usando NodeJS todos dias as 00:00 (UTC)
$scheduler->shell('mynodetask', 'node /foo/bar/script.js')->at(0, 0);
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(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. |
Como a maioria dos métodos retorna a própria instancia da classe Inphinit\Experimental\Scheduling\Task,
é possivel usando como:
$scheduler->call('mytask5', function () { ... })
->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('mytask6', function () { ... })->at(14, 30)->runInBackground(true);
$scheduler->call('mytask7', function () { ... })->at(14, 30)->runInBackground(true);
As tarefas continuarão sendo executadas na ordem em que foram declaradas. Isso significa que as tarefas em background também serão chamadas nessa mesma ordem e, caso exista uma tarefa que não seja de background à frente delas, a tarefa em background precisará aguardar. Para executar as tarefas em background antecipadamente, utilize:
$scheduler->prioritizeBackgroundTasks(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;
$dt = new DateTime('2030-01-01', new DateTimeZone('America/Sao_Paulo'));
// Executará em 2030-01-01 12:00:00
$scheduler->call('mytask1', function (Task $task) {
echo 'Hello World!';
})->once($dt);
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('mytask1', function () { ... })->at(10, 0);
// Executará todos os dias as 15:30 do horário de São Paulo
$scheduler->call('mytask2', function () { ... })->at(15, 30);
// Executará todos os dias as 20:00 do horário de São Paulo
$scheduler->call('mytask3', function () { ... })->at(20, 0);
Exemplos de uso
O método ::cron() é similar a estrutura do crontab, como pode ser visto nos exemplos:
$scheduler->call('mytask1', function () { ... })->cron($minuto, $hora, $dia, $mês, $dia_da_semana);
Alguns exemplos de uso:
| Uso | Explicação |
|---|---|
cron('*', '*', '*', '*', '*') |
Executa a cada minuto. Os cinco campos estão como *, significando qualquer minuto, qualquer hora, qualquer dia do mês, qualquer mês e qualquer dia da semana. |
cron('*/5', '*', '*', '*', '*') |
Executa a cada 5 minutos. */5 no campo de minutos significa 0, 5, 10, 15, etc. |
cron(0, '*', '*', '*', '*') |
Executa no minuto 0 de toda hora, ou seja, uma vez por hora. |
cron(30, 8, '*', '*', '*') |
Executa todos os dias às 08:30. 30 representa o minuto e 8 representa a hora. |
cron(0, 0, '*', '*', '*') |
Executa todos os dias à meia-noite. 0 no campo de minuto e 0 no campo de hora. |
cron(0, 12, '*', '*', 1) |
Executa toda segunda-feira ao meio-dia. 1 representa segunda-feira em implementações cron tradicionais. |
cron(0, 9, '*', '*', '1-5') |
Executa de segunda a sexta-feira às 09:00. 1-5 representa o intervalo de segunda a sexta. |
cron(0, 18, '*', '*', '6,0') |
Executa aos sábados e domingos às 18:00. 6,0 representa sábado e domingo em cron que usa domingo como 0. |
cron(0, 0, 1, '*', '*') |
Executa no primeiro dia de cada mês à meia-noite. O terceiro campo, 1, é o dia do mês. |
cron(30, 7, 15, '*', '*') |
Executa no dia 15 de cada mês às 07:30. |
cron(0, 10, '*', 1, '*') |
Executa todos os dias de janeiro às 10:00. 1 no campo do mês representa janeiro. |
cron(0, 0, 1, 1, '*') |
Executa à meia-noite do dia 1º de janeiro. |
cron(15, 14, 1, '*', 5) |
Executa às 14:15 quando for dia 1º e sexta-feira, observando a semântica da implementação de cron. |
cron(0, '*/2', '*', '*', '*') |
Executa a cada 2 horas, sempre no minuto zero: 00:00, 02:00, 04:00, etc. |
cron('*/10', '9-17', '*', '*', '1-5') |
Executa a cada 10 minutos, entre 09:00 e 17:59, de segunda a sexta-feira. |
cron(0, 0, '*', '*', 0) |
Executa todo domingo à meia-noite. 0 no quinto campo representa domingo em cron tradicional. |
cron(0, 0, '*', '*', '1,3,5') |
Executa à meia-noite nas segundas, quartas e sextas-feiras. A vírgula permite especificar vários valores. |
cron(0, 0, '1-7', '*', 1) |
Executa à meia-noite às segundas-feiras que caírem entre os dias 1 e 7 do mês. |
cron(0, 0, 1, '*/3', '*') |
Executa no primeiro dia a cada três meses, à meia-noite. */3 no campo de mês representa intervalos de três meses. |
cron(30, 15, '*', '*', '*') |
Executa todos os dias às 15:30. É um exemplo simples para visualizar separadamente minuto (30) e hora (15). |