O que é um Job no Laravel?
No Laravel, os Jobs executam tarefas de forma assíncrona ou em segundo plano. Eles distribuem tarefas demoradas, como envio de e-mails e processamento de arquivos, o que, consequentemente, melhora o desempenho da aplicação. Como resultado, os Jobs mantêm a aplicação responsiva ao gerenciar de forma eficaz tarefas pesadas, o que, por sua vez, aumenta a escalabilidade e evita bloqueios no sistema. Além disso, o sistema permite que as tarefas sejam reenfileiradas automaticamente em caso de erros, garantindo maior robustez no processamento.
- Enviar e-mails em massa
- Processar imagens ou vídeos
- Executar relatórios e análises de dados
- Sincronizar grandes volumes de dados entre sistemas
Por que utilizar Jobs?
- Desempenho Melhorado: Jobs garantem que tarefas pesadas não interrompam a interação do usuário, tornando a aplicação mais fluida e escalável.
- Tolerância a Falhas: Quando ocorre uma falha, os Jobs podem ser reenfileirados automaticamente. Além disso, você pode configurar o número máximo de tentativas antes de marcar o Job como falhado.
- Manutenção Facilitada: Ao separar tarefas em Jobs, você torna a organização e a manutenção do código muito mais simples, deixando-o mais legível e modular.
Como Criar um Job
Você pode criar um Job no Laravel de maneira simples. Primeiro, execute o seguinte comando Artisan:
php artisan make:job Teste
Após você executar esse comando, o Laravel cria uma classe em app/Jobs
, e o método handle
, em seguida, define a lógica do Job. Por exemplo, no código abaixo, o Job força propositalmente uma falha.
namespace App\Jobs;
use Exception;
class Teste extends Job
{
public function handle()
{
// Aqui você adiciona sua lógica de job mas vou forçar uma exceção
throw new Exception("Erro de teste");
}
}
Após a criação, podemos enfileirar ester Job com o comando:
Teste::dispatch();
Note que o comando dispatch()
pode ser disparado de várias partes da aplicação, como em rotas, controladores ou eventos. Por isso, podemos incluir uma rota de teste dessa maneira:
Route::get('/test-job', function () {
Teste::dispatch();
return 'Job enfileirado com sucesso!';
});
Uma vez que invocamos aquela rota e enfileiramos o Job Teste, podemos iniciar o worker para processá-lo e fazemos com o seguinte comando:
php artisan queue:work
Então, veja que, enquanto o worker processa os Jobs na fila, ele executa a lógica definida no método handle
de cada Job. Portanto, se ocorrer uma falha, o Laravel capturará automaticamente a exceção e tentará executar o Job novamente, conforme a quantidade de tentativas configurada para esse Job.
Onde Chamar o Dispatch
Você pode chamar o dispatch
em diferentes partes da aplicação, como:
Dentro de um Controller:
public function enviarEmail(Request $request)
{
NomeDoJob::dispatch($request->email);
return response()->json('Job enfileirado!');
}
Dentro de um Event Listener:
public function handle(UserRegistered $event)
{
NomeDoJob::dispatch($event->user);
}
Diretamente em Middleware ou Services: Você também pode chamar dispatch()
em middleware, serviços ou até mesmo em comandos artisan
, dependendo da necessidade.
Finalmente, o local onde você decide chamar dispatch()
depende do contexto em que o Job precisa ser processado.
O Que Acontece Quando Um Job É Disparado?
Ao disparar um Job no Laravel com dispatch()
, o Laravel o coloca em uma fila. Essa fila mantém os Jobs até que um worker os processe. O Laravel suporta diferentes backends para filas, como:
- Banco de Dados: Armazena os Jobs em uma tabela (
jobs
). - Redis: Mantém os Jobs na memória, proporcionando maior desempenho.
- SQS (Amazon SQS): Serviço de fila da AWS.
Você escolhe o backend configurando a variável QUEUE_CONNECTION
no arquivo .env
. Por exemplo:
QUEUE_CONNECTION=database
Enquanto o worker está em execução, ele processa cada Job na fila. Se o Laravel processar o Job com sucesso, ele o removerá da fila. No entanto, caso ocorra uma exceção durante o processamento, o Laravel oferece mecanismos automáticos para lidar com falhas.
Tratamento de Exceções
Jobs podem falhar em situações comuns, como:
- Problemas de permissões de arquivos: Se o Job lida com upload ou manipulação de arquivos, ele pode falhar devido à falta de permissões.
- Falha em integração com APIs externas: Jobs podem falhar por problemas de rede ou autenticação ao se comunicar com APIs.
O Laravel captura essas exceções automaticamente. Além disso, você pode configurar quantas tentativas o Job terá antes de o Laravel marcá-lo como falhado. Caso o número de tentativas seja excedido, o Laravel registrará o Job na tabela failed_jobs
para que você consulte o erro manualmente.
Exemplo de configuração de tentativas em um Job:
public $tries = 5; // Tentativas antes de marcar como falhado
Como Consultar Falhas de Jobs no Banco de Dados
Se você configurou o banco de dados como backend para armazenar os Jobs, siga estes passos para consultar manualmente o motivo de uma falha:
1. Verifique a tabela failed_jobs
: Os Jobs que falharam ficam registrados nessa tabela.
2. Execute uma consulta SQL para visualizar o motivo da falha:
SELECT * FROM failed_jobs WHERE id = <id_do_job>;
3. Verifique a coluna exception
: Ela contém a mensagem de erro e o stack trace da exceção.
id | connection | queue | payload | exception | failed_at |
1 | database | default | {“job”:”SendEmailJob”,”data”:{“user_id”:1}} | SQLSTATE[HY000]: General error: 1364 Field ‘email’ doesn’t have a default value | 2024-10-02 10:12:45 |
2 | redis | emails | {“job”:”ProcessReportJob”,”data”:{“report_id”:5}} | Connection refused [tcp://localhost:6379] during Redis operation | 2024-10-02 11:30:12 |
3 | database | default | {“job”:”UpdateStatsJob”,”data”:{“stats_id”:10}} | Error: Undefined variable: stats_id in UpdateStatsJob.php | 2024-10-02 12:45:00 |
Olhando Dentro do Worker
Como vimos, ao enfileirar um Job com dispatch()
, ele entra na fila, onde o worker o processa. O worker é um processo em segundo plano que monitora as filas e processa os Jobs assim que são enfileirados.
Para iniciar o worker, execute o seguinte comando:
php artisan queue:work
Quando o worker detecta um Job na fila, ele segue este fluxo:
O comando queue:work
chama o método handle
da classe WorkCommand
, que inicia o processamento dos Jobs. Em seguida, o método handle
invoca runNextJob
no worker para processar o próximo Job.
// trecho da classe: vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php
public function handle()
{
$this->worker->runNextJob($this->gatherWorkerOptions());
}
Aqui, o método runNextJob
é chamado para processar o próximo Job da fila.
Executando o Próximo Job
Assim que o worker obtém o próximo Job da fila, ele começa a executá-lo. Posteriormente, o método runNextJob
da classe Worker
captura o Job na fila e o encaminha para processamento. Logo em seguida, ele chama o método process()
, que então gerencia a execução do Job.
// trecho da classe: vendor/laravel/framework/src/Illuminate/Queue/Worker.php
public function runNextJob(WorkerOptions $options)
{
// Código para pegar o próximo job da fila
$this->process($connectionName, $job, $options);
}
Dentro do método process()
, o Laravel invoca o método fire()
. Este método, por sua vez, chama o método handle()
do Job, onde a lógica de processamento definida por você é executada.
// vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php
public function fire()
{
$payload = $this->payload();
$this->instance = $this->resolve($payload);
$this->instance->handle();
}
Neste ponto, o Job está sendo executado com base no código dentro do método handle()
.
Tratamento de Exceções Durante o Processamento
Quando uma exceção ocorre durante a execução do Job (no método handle()
), o Laravel captura automaticamente essa exceção. o método process()
captura essa exceção durante a execução, gerenciando-a dentro de um bloco try-catch
.
Entretanto, se o código lançar uma exceção, o método handleJobException
a tratará. Ele pode reenfileirar o Job, dependendo do número de tentativas configuradas, ou marcá-lo como falhado.
// vendor/laravel/framework/src/Illuminate/Queue/Worker.php
public function process($connectionName, $job, WorkerOptions $options)
{
try {
$job->fire(); // Executa o Job
} catch (Exception $e) {
// Captura a exceção e trata
$this->handleJobException($connectionName, $job, $options, $e);
}
}
Tratamento de Exceção no Job
Quando o método handle
do Job lança uma exceção, o bloco catch
no método process
captura essa exceção. Em seguida, o método handleJobException
lida com ela.
try {
//
} catch (Exception $e) {
$this->handleJobException($connectionName, $job, $options, $e);
}
O Laravel oferece suporte para reexecutar o Job automaticamente. No entanto, se o limite de tentativas for atingido, o Job será marcado como falhado. Além disso, o método handleJobException
marca o Job como falhado, se necessário.
// vendor/laravel/framework/src/Illuminate/Queue/Worker.php
protected function handleJobException($connectionName, $job, WorkerOptions $options, $e)
{
$this->markJobAsFailedIfWillExceedMaxAttempts(
$connectionName, $job, $options->maxTries, $e
);
// Código para registrar a falha e disparar eventos
}
Então, esse método decide se o Job deve ser reenfileirado para novas tentativas ou marcado como falhado.
Registro de Job que falhou
Quando um Job falha após todas as tentativas configuradas, o Laravel registra essa falha na tabela failed_jobs
. A tabela mantém um histórico dos Jobs que não conseguiram ser concluídos. Dessa forma, você pode inspecionar as falhas, e se necessário, reprocessar manualmente.
O método failJob
realiza o registro do Job na tabela failed_jobs
:
// vendor/laravel/framework/src/Illuminate/Queue/Worker.php
protected function markJobAsFailedIfWillExceedMaxAttempts($connectionName, $job, $maxTries, $e)
{
if ($job->attempts() >= $maxTries) {
$this->failJob($connectionName, $job, $e);
}
}
protected function failJob($connectionName, $job, $e)
{
// Registra a falha na tabela `failed_jobs`
$this->fail($job, $e);
}
Além disso, o aquivo queue.php
contem a configuração da tabela failed_jobs
. Contudo, geralmente você define o driver no arquivo .env
, como:
QUEUE_CONNECTION=redis
// config/queue.php
'failed' => [
'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
'database' => 'mysql',
'table' => 'failed_jobs',
],

Resumo
- Criação do Job: Crie o arquivo
Teste.php
com o métodohandle
. - Disparo do Job: Execute com
Teste::dispatch()
. - Processamento pelo Worker: O comando
queue:work
chamahandle
emWorkCommand
, que então invocarunNextJob
no Worker. O Worker, por sua vez, chamaprocess()
, que executa o Job comfire()
e aciona o métodohandle()
. - Tratamento de Exceções: Se ocorrer uma exceção,
process()
captura e trata no métodohandleJobException
. - Registro de Falha: Caso o Job falhe após todas as tentativas, o método
markJobAsFailedIfWillExceedMaxAttempts
o registra na tabela de falhas.

Conclusão
Utilizar Jobs no Laravel melhora tanto a escalabilidade quanto a performance da aplicação, pois processa tarefas demoradas de forma assíncrona sem interferir no fluxo principal. Como resultado, a aplicação oferece uma experiência de usuário mais rápida e responsiva, mesmo em operações complexas.
Além disso, o Laravel proporciona um sistema robusto para tratar exceções, monitorar e reenfileirar Jobs que falham, minimizando riscos e aumentando a confiabilidade. Dessa forma, o fluxo completo de Jobs assegura que a aplicação gerencie grandes volumes de tarefas sem comprometer o desempenho.
Saiba Mais
Se você deseja se aprofundar na configuração e no funcionamento de Jobs no Laravel, confira os seguintes recursos:
- Documentação Oficial do Laravel sobre Filas: Saiba como configurar e otimizar filas no Laravel, incluindo drivers como banco de dados, Redis e SQS.
- Configuração de Filas no Laravel: Explore a configuração de filas, prioridades e tentativas.
- Reenfileiramento de Jobs Falhados: Aprenda a lidar com Jobs que falham durante o processamento.
- Filas Baseadas em Banco de Dados: Veja como usar o banco de dados como backend de filas.
- Processamento com Workers: Entenda como configurar e executar workers.
- Gerenciamento de Exceções em Jobs: Veja como o Laravel gerencia exceções e falhas em Jobs.
- Uso de Redis com Filas: Conheça as vantagens do Redis como backend de filas no Laravel.