Desenvolvimento Laravel4 min de leitura

Modernização com Laravel: filas, idempotência e migração segura

Modernize uma aplicação PHP legada de forma incremental, com gravações transacionais, jobs seguros para reprocessar e um plano de rollback ensaiado.

Uma transação da aplicação alimentando uma fila e workers independentes

A resposta curta

Migre uma capacidade de negócio por vez. Proteja as invariantes do banco de dados com transações e restrições, torne os jobs da fila seguros para reprocessar e verifique a entrega e o rollback antes de mover a próxima rota.

Escolha um escopo pequeno o bastante para verificar

Uma migração incremental pode reduzir o escopo de cada release, mas não está livre de riscos. Comece por um fluxo delimitado cujas entradas, saídas e responsáveis sejam bem conhecidos. Mapeie o modelo de dados legado, os efeitos externos e as dependências de relatórios antes de mover tráfego.

Registre como linha de base a taxa de erros, a latência das respostas, a idade da fila e os resultados de negócio, como pedidos concluídos. Direcione um conjunto controlado de requisições para a nova implementação e mantenha um caminho claro de volta. Evite migrar armazenamento, framework, pagamentos e interface ao mesmo tempo, a menos que as dependências exijam.

Mantenha a gravação crítica transacional

Valide as permissões e a entrada e, em seguida, grave a transição de estado mínima válida dentro de uma transação de banco de dados. Use restrições de unicidade para invariantes, como uma única referência externa por pedido. Locks de linha ou atualizações condicionais podem proteger transições concorrentes quando usados corretamente.

Um lock no Redis pode coordenar o trabalho, mas uma concessão expirada, uma queda ou uma chave com escopo errado podem permitir sobreposição. Ele não substitui as restrições do banco de dados. Documente qual sistema é dono de cada invariante e teste-a com requisições simultâneas.

Despache somente depois que os dados forem confirmados

Um worker pode rodar antes que a transação que o originou seja confirmada. O Laravel oferece o despacho após o commit, para que os jobs não leiam registros não confirmados ou revertidos. Em uma aplicação Laravel 12, um padrão básico é:

DB::transaction(function () use ($validated) {
    $order = Order::create($validated);
    ProcessOrder::dispatch($order->id)->afterCommit();
});

Este exemplo é incompleto de propósito: autorização, tratamento de requisições duplicadas e validação de negócio ficam ao redor dele. O despacho após o commit também não elimina a janela de falha entre o commit no banco e a entrega a uma fila externa. Para fluxos que exigem entrega durável, considere um outbox transacional e um publicador com novas tentativas.

Projete os jobs para execução “pelo menos uma vez”

Parta do princípio de que um job pode ser executado mais de uma vez. Grave uma chave de idempotência, registre as operações concluídas e use o mecanismo de idempotência do provedor externo quando existir. Não marque um job como concluído antes de o efeito externo ter dado certo. Concilie resultados incertos em vez de repetir às cegas uma cobrança ou um envio.

  • Defina timeouts, limites de tentativas e intervalos de espera de acordo com a operação.
  • Mantenha o timeout do worker menor que o intervalo de nova tentativa da fila, com folga para o desligamento, para reduzir tentativas sobrepostas.
  • Monitore os jobs com falha e a idade da fila; uma resposta HTTP 202 significa “aceito”, não “concluído”.
  • Reinicie os workers de longa duração durante os releases para que carreguem o código certo.

Ensaie falhas e rollback

Teste um webhook duplicado, a queda de um worker depois de uma chamada externa, um deadlock no banco de dados, uma indisponibilidade da fila e um deploy que falhou. Verifique os registros e efeitos resultantes, não apenas a resposta HTTP. Adicione conciliação para o trabalho que foi aceito, mas nunca concluído.

Use alterações de esquema retrocompatíveis enquanto as duas aplicações estiverem ativas. Defina as condições de rollback antes do release e confira se a aplicação antiga consegue ler os dados gravados pela nova. Mantenha uma única fonte da verdade para cada registro até que a sincronização seja projetada explicitamente.

Perguntas frequentes

Quando o processamento deve continuar síncrono?

Quando quem chama precisa de um resultado imediato e definitivo, e o trabalho é curto o bastante para caber no tempo de resposta previsto. Filas são úteis para trabalho que pode ser adiado, mas trazem suas próprias responsabilidades de entrega, visibilidade e recuperação.

O despacho após o commit garante que o job chegue à fila?

Não. Ele impede que um job seja despachado antes do commit da transação, mas ainda pode ocorrer uma falha entre o commit e a entrega a uma fila externa. Se você precisa de entrega durável, avalie um outbox transacional com um publicador com novas tentativas e conciliação.

Como evitar que novas tentativas criem pagamentos ou pedidos duplicados?

Use chaves de idempotência persistentes, restrições no banco de dados e o mecanismo de idempotência do provedor externo quando existir. Registre os resultados e concilie as respostas incertas. Um lock de curta duração, sozinho, não cobre todas as quedas nem todas as janelas de nova tentativa.

O que facilita o rollback de uma migração incremental?

Mover um fluxo delimitado, manter um caminho claro de roteamento para a implementação anterior e usar alterações de esquema retrocompatíveis. Teste se a aplicação antiga consegue ler os registros criados pela nova. Defina antes do release os gatilhos de rollback, com base em erros e resultados de negócio.

Fontes e leituras recomendadas

Continue explorando

Compare estratégias de renderização ou vamos conversar sobre uma migração para Laravel.

Paul Edward

Escrito por Paul Edward

Desenvolvedor web full-stack sênior que trabalha com PHP, Laravel, WordPress e sistemas web com IA.

Mais sobre o Paul

Leave a Reply

Your email address will not be published. Required fields are marked *

Carregando uma verificação rápida… (requer JavaScript)

Briefing do projeto Etapa 1 de 2 · O trabalho

O que você quer construir?

Um parágrafo já basta para começar. Se não for um trabalho para mim, eu digo e indico alguém melhor.

O trabalho

Marque tudo o que se aplica.

Plataforma

“Não sei” é uma resposta perfeitamente válida.

O que você quer construir, e o que isso precisa fazer pelas pessoas que vão usar? Escreva do jeito que você diria em voz alta.

0 / 1200

Duas etapas. Menos de um minuto.