Leonardo Peron5 min de leitura
Toda integração é escrita imaginando que o outro lado responde. Ele responde na maior parte do tempo — e é justamente por isso que a falha, quando vem, pega a operação sem plano. O ERP fica fora por vinte minutos numa terça de manhã, e a pergunta que ninguém fez antes aparece pronta: o que aconteceu com os pedidos que chegaram nesses vinte minutos?
Há três respostas possíveis, e só uma delas é aceitável.
As três respostas
Sumiram. A integração tentou entregar, recebeu erro, registrou uma linha no log e seguiu para o próximo. É o comportamento padrão de quase toda integração escrita às pressas, e o pior de todos, porque o prejuízo só aparece dias depois, quando um cliente cobra um pedido que a empresa não sabe que existe.
Travaram tudo. A integração parou no primeiro erro e não processou mais nada. Menos grave que sumir, porque nada se perde, mas a fila cresce e a recuperação vira um evento manual.
Ficaram guardados e entraram sozinhos depois. É o único desenho que trata indisponibilidade como o que ela é: uma condição normal de operação, não uma exceção.
A fila é o mínimo
O que separa a terceira resposta das outras duas é simples: o recebimento e a entrega precisam ser duas etapas separadas.
Quando a integração recebe um evento — um pedido pago, uma nota emitida, um cadastro alterado — a primeira coisa que ela faz é gravar esse evento num lugar que sobrevive a reinício. Só depois, num segundo momento, tenta entregar ao sistema de destino.
Parece burocracia e é o que muda tudo. Com as duas etapas juntas, a indisponibilidade do destino destrói o evento na origem. Separadas, o destino pode ficar fora o dia inteiro que o evento continua ali, esperando.
Não precisa ser uma ferramenta de fila dedicada. Uma tabela com estado
pendente, entregue e falhou resolve a maioria dos casos, e tem a vantagem
de ser consultável por quem opera — o que uma fila em memória não é.
Retentativa: quantas vezes e de quanto em quanto
Guardar o evento resolve a perda. Falta decidir como voltar a tentar, e o erro mais comum aqui é tentar de novo imediatamente, em laço.
Um destino que caiu por sobrecarga recebe, de uma integração ansiosa, mais carga ainda — e a recuperação dele demora mais por causa de quem estava tentando ajudar. O intervalo entre tentativas precisa crescer: um minuto, depois dois, depois quatro, até um teto. É o que se chama de recuo exponencial, e existe porque a maior parte das indisponibilidades se resolve sozinha em minutos.
Duas decisões acompanham:
Quantas tentativas antes de desistir. Não existe número universal. O que existe é a obrigação de ter um limite: sem ele, um evento que nunca vai passar — um pedido com CNPJ inválido, por exemplo — fica tentando para sempre e consome a fila inteira.
Onde o evento vai quando desiste. Precisa ir para algum lugar visível. Uma lista de "não entregues" que alguém olha todo dia é o suficiente, e é infinitamente melhor que o log, onde a linha se perde entre milhares de outras.
Nem todo erro merece retentativa
Aqui está a distinção que a maioria das integrações não faz, e que separa uma fila útil de uma fila entupida.
Erro do outro lado — indisponibilidade, tempo esgotado, erro interno do servidor — é temporário por natureza. Retentar faz sentido.
Erro do nosso lado — campo obrigatório faltando, formato inválido, autenticação recusada, registro que não existe no destino — não melhora com o tempo. A décima tentativa vai falhar exatamente como a primeira.
Tratar os dois do mesmo jeito produz o sintoma clássico: uma fila com milhares de tentativas por hora, quase todas de dois ou três eventos defeituosos, e os eventos bons esperando atrás deles.
A regra prática: erro que o outro lado pode resolver sozinho vai para retentativa; erro que precisa de correção de dado ou de configuração vai direto para a lista de intervenção humana.
A armadilha da retentativa
Toda retentativa carrega uma pergunta desconfortável: e se a primeira tentativa tiver funcionado, e só a resposta ter se perdido?
Acontece com frequência. A integração envia o pedido, o destino cria o pedido, e a conexão cai antes da confirmação voltar. Do lado de cá, parece falha. A retentativa cria o pedido de novo.
A proteção é a mesma que impede webhook repetido de duplicar pedido: idempotência. Cada evento carrega um identificador estável da origem, e a operação de criação no destino usa esse identificador como chave única. Chegando dez vezes, cria uma vez.
Sem isso, a fila com retentativa é uma máquina de duplicar registro — e o remédio fica pior que a doença que ele veio curar.
Quando o destino não oferece chave de idempotência, e alguns ERPs realmente não oferecem, o jeito é consultar antes de criar. Custa uma chamada a mais e resolve.
O alerta que precisa existir
Fila que ninguém observa é fila que acumula em silêncio até o dia em que alguém percebe que o financeiro está sem lançamento há uma semana.
Dois alarmes cobrem quase tudo:
- Idade do evento mais antigo pendente. Se algo está esperando há mais de uma hora, alguém precisa saber. Esse número diz mais que a quantidade de itens na fila, porque mil eventos entregues em cinco minutos não são problema e um evento parado há seis horas é.
- Qualquer coisa na lista de não entregues. Não deveria ser rotina. Se virou rotina, o desenho tem um defeito que a retentativa está mascarando.
O teste que confirma
Não dá para confiar num desenho de resiliência que nunca foi exercitado. O teste é direto e vale fazer antes de a integração entrar em produção:
- Derrube o destino de propósito — desligue, bloqueie, aponte para um endereço inválido.
- Faça a origem gerar cinco eventos.
- Suba o destino de volta.
- Confirme que os cinco entraram, uma vez cada um, sem ninguém tocar em nada.
Integração que não passa nesse teste não está pronta. Está apenas ainda não tendo dado errado.