Pular para conteúdo

Aula 18 - Queues, Jobs e Processamento em Segundo Plano 📦

Objetivo Pedagógico

Objetivo: Arquitetura assíncrona com filas de mensageria no Laravel, criação de Jobs despacháveis, priorização de filas e monitoramento em tempo real com Laravel Horizon.


📑 1. Fundamentos Teóricos & Análise Técnica

No desenvolvimento de sistemas web em PHP, onde tradicionalmente cada requisição opera no modelo Share-Nothing e é descartada ao final do script, o sistema de Queues (Filas) do Laravel é fundamental para permitir operações de longa duração sem bloquear a resposta ao usuário.

Funcionamento do ecossistema de filas do Laravel: 1. Jobs Despacháveis (ShouldQueue): Classes de trabalho que implementam a interface ShouldQueue. Ao chamar ProcessInvoice::dispatch($invoice), o Laravel serializa o modelo e o payload, gravando a mensagem no broker (geralmente Redis). 2. Workers Contínuos (queue:work): Processos PHP de longa duração (long-running processes) gerenciados por utilitários como Supervisor ou Systemd, que retiram jobs da fila e os executam sequencialmente. 3. Laravel Horizon: Painel visual e gerenciador de filas em tempo real para Redis, fornecendo balanceamento automático de carga, métricas de vazão (throughput) e controle de jobs que falharam (Failed Jobs).

📐 Arquitetura Conceitual & Diagrama de Fluxo

sequenceDiagram
    autonumber
    actor User as Usuário Web
    participant App as Laravel Web App
    participant Redis as Redis Queue Broker
    participant Horizon as Laravel Horizon Workers

    User->>App: Solicita Exportação de Relatório
    App->>Redis: Despacha Job (ExportReportJob::dispatch)
    App-->>User: 200 OK ("Exportação iniciada em background!")
    Redis->>Horizon: Entrega Job para Execução
    Note over Horizon: Gera Arquivo Excel / CSV em Segundo Plano
    Horizon->>App: Notifica Conclusão via E-mail / WebSocket

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Interface ShouldQueue: A simples presença da interface transforma qualquer método síncrono em um processo assíncrono em fila. - Políticas de Tentativas e Timeout: Configuração de $tries, $backoff e $timeout para controle rigoroso de falhas. - Gerenciamento de Falhas: Registro automático de jobs com erro na tabela failed_jobs com inspeção de stack trace. - Filas Prioritárias: Divisão de tráfego entre filas de alta prioridade (high), padrão (default) e baixa (low).


🛠️ 2. Implementação Prática em Laravel Queues, Redis e Horizon

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// SendWelcomeNotificationJob.php (Job Despachável com Retry em Laravel)
<?php

namespace App\Jobs;

use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class SendWelcomeNotificationJob implements ShouldQueue {
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 3;
    public array $backoff = [10, 30, 60]; // Segundos de espera entre retries

    public function __construct(public User $user) {}

    public function handle(): void {
        // SerializesModels reidrata a instância do usuário a partir do banco
        logger()->info("Enviando e-mail de boas-vindas para: {$this->user->email}");

        // Simula disparo de notificação
        sleep(2);
    }

    public function failed(\Throwable $exception): void {
        logger()->error("Falha definitiva no envio de notificação: " . $exception->getMessage());
    }
}

💡 Análise Passo a Passo do Código

  1. Trait SerializesModels: Serializa apenas o ID do usuário para a fila do Redis e busca o registro atualizado no banco na hora da execução do job.
  2. Backoff Exponencial em Array: $backoff = [10, 30, 60] define intervalos crescentes de espera caso ocorra falha temporária de rede.
  3. Gancho failed(): Método executado automaticamente quando todas as tentativas se esgotam, permitindo alertar a equipe de suporte.

🎯 3. Próximos Passos & Sequência Didática