O Laravel 13.31 adiciona jobs interrompíveis, permitindo que os workers de fila capturem o sinal SIGTERM enviado durante deployments e encerrem de forma limpa, em vez de abortar uma tarefa no meio do caminho. Equipes que executam jobs longos — processando dezenas de milhares de linhas, enviando e-mails em massa ou gerando relatórios — se beneficiam porque os dados permanecem consistentes quando um novo release é lançado.
Por que os deployments têm matado jobs
Quando uma nova versão chega, gerenciadores de processo como Supervisor, Docker e Kubernetes dizem aos workers existentes para parar enviando um SIGTERM, um pedido educado para terminar. A maioria dos workers espera o job atual terminar antes de sair. O problema surge quando o gerenciador concede apenas alguns segundos para cumprir o pedido. Se um job precisa de minutos, o gerenciador escala para SIGKILL, matando o processo instantaneamente. O job nunca atinge um estado consistente, deixando registros parcialmente atualizados, arquivos órfãos ou trabalho duplicado.
A resposta do Laravel: interrupção cooperativa
O Laravel 13.31 introduz um contrato chamado Interruptible que uma classe de job pode implementar para se tornar ciente da solicitação de encerramento. Quando o SIGTERM chega, o Laravel chama o método interrupted() do job. O framework não interrompe o job automaticamente; o job deve verificar uma flag que o Laravel define e sair por conta própria. Esse modelo cooperativo permite que os desenvolvedores finalizem a iteração atual do loop, revertam alterações parciais ou escrevam um checkpoint antes de sair.
Como tornar um job interrompível
- Implemente o contrato – adicione
implements Interruptibleà definição da classe do job. - Verifique a flag dentro do loop de trabalho – insira uma verificação em cada iteração para ver se o job deve parar.
- Realize a limpeza – em
interrupted(), persista qualquer estado que permita ao job retomar mais tarde, ou registre a interrupção para análise posterior.
A maior armadilha: não use --once
Executar o worker de fila com php artisan queue:work --once desativa completamente o tratamento de sinais. O worker processa um único job e sai, mas nunca registra o handler do SIGTERM. Consequentemente, qualquer job interrompível ignora a solicitação de encerramento e é morto no meio do processo. Esse padrão aparece em containers acionados por cron e deployments de execução única. Corrija isso executando o modo daemon (php artisan queue:work) sempre que precisar de jobs interrompíveis.
Monitorando interrupções
O Laravel dispara dois eventos nos quais você pode se conectar:
- WorkerInterrupted – emitido sempre que qualquer worker recebe um SIGTERM. Registrar este evento oferece uma visão de alto nível de com que frequência os deployments interrompem os workers.
- JobInterrupted – emitido apenas se o job atual implementar o contrato Interruptible. Use este evento para acionar a limpeza específica do job, como excluir arquivos temporários ou atualizar um marcador de "última linha processada".
Ouvir esses eventos permite que as equipes criem dashboards que mostram o impacto do deployment e identifiquem jobs que são interrompidos com frequência.
O relatório de tamanho da fila recebe um ajuste
O lançamento adiciona um método totalSize() ao gerenciador de filas, retornando o número total de jobs pendentes em todas as filas. O valor é confiável para drivers baseados em banco de dados e Redis, que relatam contagens reais. Drivers como SQS, Sync e Beanstalkd ainda retornam zero porque não expõem uma contagem através da API do Laravel. Equipes que usam SQS devem continuar confiando nas métricas do CloudWatch para a profundidade da fila.
O que isso significa para diferentes configurações
- Docker/Kubernetes – o período de encerramento suave (graceful shutdown) agora pode ser usado de forma eficaz. Estenda o período de tolerância para o encerramento para que os jobs tenham alguns segundos para notar a flag e sair de forma limpa.
- Supervisor – defina
stopwaitsecsem um valor superior ao tempo que você espera que um job leve para terminar após receber a flag de interrupção. - Jobs legados – revise qualquer job que execute por mais tempo que o timeout do gerenciador e, onde for possível, torne-o interrompível.
Contraponto: complexidade adicional
O recurso não substitui uma configuração de timeout adequada. Se o loop de um job nunca verificar a flag de interrupção, o gerenciador ainda enviará SIGKILL. As equipes devem auditar caminhos de código de longa execução e inserir verificações em pontos de interrupção lógicos. Alguns desenvolvedores podem achar o boilerplate extra — implementar um contrato e adicionar verificações de flag — pouco atraente para jobs curtos que já terminam dentro da janela de encerramento.
Checklist de ação
- Escaneie os scripts de deployment em busca da flag
--oncee substitua-a pelo modo daemon onde jobs interrompíveis forem utilizados. - Identifique os jobs de execução mais longa (aqueles que processam dezenas de milhares de linhas ou rodam por vários minutos) e adicione o contrato Interruptible.
- Insira uma verificação de flag dentro de cada iteração do loop e mova qualquer código de finalização necessário para o método
interrupted(). - Vincule listeners aos eventos
WorkerInterruptedeJobInterruptedpara coletar métricas sobre a frequência com que os deployments afetam o processamento. - Para filas do Redis ou de banco de dados, use
totalSize()para monitorar o backlog; para SQS, mantenha os alarmes do CloudWatch ativos.
Trate os desligamentos causados por deployments como uma etapa coordenada, em vez de uma interrupção abrupta. O Laravel 13.31 mantém os dados consistentes e reduz as dores de cabeça operacionais de jobs inacabados. A contrapartida é um aumento modesto na responsabilidade do código, mas as equipes que dependem de processamento pesado em segundo plano ganham um ambiente de produção mais confiável.
