Uma das vantagens de YeAPF ser orientado à criação de aplicativos chamados apenas por API é a uniformização da chamada. Com isso estamos dizendo que todas as chamadas são feitas do mesmo jeito com o que o programador pode esquecer de como inventou a roda da última vez, já que vai ser sempre do mesmo jeito. Ou, um grupo de programadores pode dividir suas tarefas e alternar responsabilidades que as peças vão acabar se encaixando.
Pois bem, uma outra vantagem é o processamento de tarefas de longa duração. Na realidade é um efeito colateral positivo mais do que uma vantagem propositalmente buscada.
Entendemos por “tarefa de longa duração”, aquele processo que não se encaixa nos 30-60 segundos que o PHP tem por padrão para responder a uma requisição de um cliente (seja este humano ou não).
Pense por exemplo, no que demora enviar um e-mail personalizado a cada cliente ou interessado do seu sistema on-line. Ou a geração do arquivo de remessa de um lote de boletos para um banco. Nada disso cabe nos 30-60 segundos que você tem por padrão e -mesmo que você tem a habilidade de extorquir o PHP para obter mais tempo- também não é prudente manter o usuário ocioso por mais do que 15 segundos. Ele com certeza vai clicar no botão de gerar remessa de novo para que “o processo vá mais rápido”.
É aqui que entram as tarefas de longa duração.
Tomemos o exemplo da geração dos boletos bancários. Digamos que seu lote é de 2500 boletos e cada boleto, além de ser gerado, será enviado por e-mail para o cliente.
Um primeiro evento seria o que o cliente dispara ao escolher o escopo dos seus boletos: Por exemplo: Junho/2015, Pato Branco/PR. O programador faia uma invocação mais ou menos assim:
ycomm.invoke(
"boletos",
"gerarRemessa",
{ mes: "06/2015", cidade: "Pato Branco", uf: "PR" },
function(status, error, data) {
}
);
Por outro lado, essa invocação seria processada pelo PHP em um script muito parecido com este:
function qboletos($a) {
global $userContext, $sysDate, $u,
$fieldValue, $fieldName,
$userMsg, $xq_start;
$useColNames = true;
$countLimit=20;
$ret='';
extract(xq_extractValuesFromQuery());
$xq_start=isset($xq_start)?intval($xq_start):0;
switch($a)
{
case 'gerarRemessa':
/* instancio o gerente de tarefas do YeAPF */
$tarefa=new YTaskManager();
/* monto os parametros que recebi do invoke */
$params=array(
'mes'=>$mes,
'cidade'=>$cidade,
'uf'=>$uf
);
/* transformo em json */
$params=json_encode($params);
/* crio a tarefa com 340 segundos de vida máxima por interação do laço */
$tarefa->createNewTask("boletos", "gRemessa", $params, 340);
/* faço qualquer outra coisa que a tarefa precise antes de começar a rodar ela */
/* ... */
/* habilito a tarefa */
$tarefa->enableTask();
break;
}
xq_produceReturnLines($ret, $useColNames, $countLimit);
}
}
Com isso nossa tarefa estaria criada. Repare que em lugar do evento “gerarRemessa” utilizei “gRemessa” mas apenas o fiz aos efeitos de que fique claro onde entra cada parte. Nada impede de utilizar “gerarRemessa” já que a tarefa vai entrar na funçao tboletos() e não na qboletos()
Agora vamos criar o laço da tarefa em si mesma. A recomendação é colocar no mesmo PHP que temos a qboletos() para que fique todo junto. O laço ficaria mais ou menos assim supondo que sua tabela se chame “boletos”
function tboletos($a)
{
global $sysDate, $ytasker, $xq_start;
/* publico o contexto operacional como se fossem variáveis locais:
xq_start, xq_target, j_params */
extract($ytasker->getTaskContext());
/* garanto que xq_start seja um inteiro positivo */
$xq_start=isset($xq_start)?intval($xq_start):0;
switch($a)
{
case 'gRemessa':
$sql="select * from boletos where data>='$dataInicial' and data<='$dataFinal' offset $xq_start";
$q=db_query($sql);
/* enquanto o sistema me deixe rodar a tarefa e tenha dados da tabela... */
while (($ytasker->taskCanRun()) && ($d=db_fetch_array($q))) {
/* ... gero o boleto
... acrescento ele à remessa
... envio e-mail */
/* incremento o 'ponteiro' para a tabela */
$xq_start++;
/* indico à tarefa o novo ponto de começo caso caia/finalize/seja suspensa daqui até a volta do laço */
$ytasker->advanceTo($xq_start);
}
break;
}
}
Agora a unica coisa que falta é chamar regularmente suas tarefas (todas elas). Isto é, fazer com que o script encarregado de tocar as tarefas seja executado regularmente. No seu crond local acrescente então uma entrada assim para chamar ele a cada minuto:
*/1 * * * * wget http://example.com/task.php?s=yeapf&a=tick
Pronto.
Caso esteja utilizando Windows, o lance é o mesmo utilizando o gerenciador de tarefas agendadas dele. Apenas instale wget.
Já se estiver usando o cron do próprio hospedeiro, pode utilizar o yeapf_tick.php assim:
*/1 * * * * /usr/bin/php yeapf_ticker.php