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

  1. Implemente o contrato – adicione implements Interruptible à definição da classe do job.
  2. Verifique a flag dentro do loop de trabalho – insira uma verificação em cada iteração para ver se o job deve parar.
  3. 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 stopwaitsecs em 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

  1. Escaneie os scripts de deployment em busca da flag --once e substitua-a pelo modo daemon onde jobs interrompíveis forem utilizados.
  2. 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.
  3. 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().
  4. Vincule listeners aos eventos WorkerInterrupted e JobInterrupted para coletar métricas sobre a frequência com que os deployments afetam o processamento.
  5. 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.