Os trabalhos em fila com falha no Laravel 5.1 falham no método fail (), evitam que o manipulador de eventos com falha na fila seja chamado
Estou testando as funções de fila no Laravel 5.1. Posso fazer trabalhos na fila da minha tabela db, chamados trabalhos, e posso executá-los com êxito. Também criei uma tabela de falha de fila chamada failed_jobs. Para testá-lo, dentro da tabela jobs eu manipulo os dados da carga útil para fazê-lo falhar e, em seguida, executo o daemon do trabalhador da fila, para que ele coloque o job na tabela fail_jobs após uma falha na tentativa:
php artisan queue:work --daemon --tries=1 --queue=myqueue
Quando o trabalho falha, ele é imediatamente colocado na tabela failed_jobs conforme o esperado.
Para sua informação, configurei as coisas exatamente como os documentos do Laravel 5.1 recomendam:
http://laravel.com/docs/5.1/queues#dealing-with-failed-jobs
Tentei registrar meu evento de falha na fila no método boot () do AppServiceProvider, conforme descrito nos documentos:
Queue::failing(function ($connection, $job, $data) {
Log::error('Job failed!');
});
Eu também tentei o método failed () dentro dos scripts de trabalho reais, como segue:
/**
* Handle a job failure.
*
* @return void
*/
public function failed()
{
Log::error('failed!');
}
De qualquer maneira, nenhum desses eventos é acionado quando o trabalho na fila falha. Não vejo nada nos logs, exceto pelo rastreamento da pilha de exceções que eu fiz ocorrer de propósito. O Laravel 5.1 tem um bug aqui ou estou faltando alguma coisa?
ATUALIZAR:
Eu fiz mais algumas pesquisas. Quando ocorre uma falha no trabalho na fila, a lógica para lidar com essa falha está em vendor / laravel / framework / src / Illuminate / Queue / Worker.php:
protected function logFailedJob($connection, Job $job)
{
if ($this->failer) {
$this->failer->log($connection, $job->getQueue(), $job->getRawBody());
$job->delete();
$job->failed();
$this->raiseFailedJobEvent($connection, $job);
}
return ['job' => $job, 'failed' => true];
}
O que acontece é que a função fail () nunca é executada e impede que a próxima função, raiseFailedJobEvent () seja chamada. É como se o script parasse silenciosamente quando fail () fosse chamado. Agora, se eu reverter a ordem dessas linhas, posso acionar o raiseFailedJobEvent () e se registrar um manipulador de eventos de fila no EventServiceProvider.php ou AppServiceProvider.php, posso verificar se é acionado e posso lidar com êxito com o evento. Infelizmente, a falha () antes do raiseFailedJobEvent () impede que esse evento ocorra.
ATUALIZAR:
O problema parece resultar de como eu o faço falhar. Se eu corromper deliberadamente os dados na tabela da fila de trabalhos, o método failed () nunca será chamado. Há um rastreamento de pilha nos logs:
Stack trace:
#0 [internal function]: Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(8, 'unserialize():
Se eu for para o fornecedor / laravel / framework / src / Illuminate / Queue / Worker.php e forçá-lo a falhar sempre que for executado (de uma maneira sem exceção, é claro), a falha () será chamada. O problema, obviamente, é como sei como essa fila se comportará em uma falha do mundo real? Se dados corrompidos do banco de dados causarem uma falha e ainda impedirem que a chamada de falha () seja inútil. E se houver uma corrupção real dos dados da fila db no mundo real?