Integrar dois sistemas sem perder dados no caminho
Novas tentativas, idempotência e rastreabilidade: as três coisas que separam uma integração que funciona de uma que parece funcionar.
Quase todas as integrações quebradas que precisei consertar começaram igual: alguém escreveu um script que lê de um lado e escreve do outro. Funcionou. Deixaram rodando. Seis meses depois faltam notas fiscais e ninguém sabe desde quando.
O script não estava mal escrito. Faltavam três coisas que ninguém pede na reunião inicial, porque não aparecem até falharem.
1. A rede falha, e falha na pior hora
Quando seu código chama uma API, há três finais possíveis: funcionou, falhou, ou você não sabe. O terceiro é o interessante.
Se a conexão cai depois que o pedido saiu mas antes de a resposta chegar, o seu lado registra um erro e o outro lado registra um cadastro. Você tenta de novo, e agora há duas notas.
A resposta não é “tentar menos”. É tentar com cabeça:
- Backoff exponencial com jitter. Se você tenta a cada segundo, quando o outro sistema cai todos os seus processos o martelam juntos e impedem que ele se levante. Espere 1 s, 2 s, 4 s, 8 s, e some um acaso de até um segundo para que não se sincronizem.
- Um teto. Depois de N tentativas, a mensagem vai para uma fila à parte e alguém olha. Tentar para sempre é esconder o problema.
- Saiba o que se repete. Um 503 se repete. Um 400 não: o pedido está errado e vai continuar errado. Repetir um 400 é gastar recursos para falhar mais tarde.
2. Idempotência: poder repetir sem quebrar
Se o ponto anterior te deixa repetindo, você precisa que repetir seja inofensivo. Isso se chama idempotência e é a peça mais pulada.
A forma prática: cada operação leva uma chave própria, estável, derivada do dado e não do momento. O número da nota serve. Um UUID gerado antes de enviar, também. Date.now() não, porque muda a cada tentativa.
O receptor guarda essas chaves e, se vê uma repetida, devolve o resultado anterior em vez de criar algo novo. Se o receptor é um sistema alheio que não faz nada disso, você faz: antes de cadastrar, pergunta se já existe. É uma chamada a mais e evita a duplicata.
Uma integração idempotente pode ser rodada inteira de novo depois de um desastre. Uma que não é não pode ser tocada sem medo, e o medo é o que faz ninguém consertar.
3. Rastreabilidade: poder responder “o que aconteceu com o pedido 4412?”
Essa é a que vai salvar a sua relação com o cliente.
Cada mensagem que cruza leva um identificador de correlação que atravessa de ponta a ponta e aparece em todos os registros. Quando alguém pergunta por um pedido, você busca esse identificador e vê a história completa: quando entrou, quantas tentativas houve, o que o outro lado devolveu, quando foi aceito.
Sem isso, a resposta honesta para “o que aconteceu com o 4412?” é “não sei”, e essa resposta custa mais do que todo o desenvolvimento.
Dois detalhes que importam: guarde o corpo do pedido e da resposta, pelo menos por um tempo, porque “devolveu erro” não serve de nada sem a mensagem; e não guarde dados pessoais de que não precisa, porque o registro também é um lugar por onde as coisas vazam.
O mínimo para dormir tranquilo
Se você está prestes a conectar dois sistemas e tem pouco tempo, a ordem é esta:
- Chave de idempotência em cada operação.
- Novas tentativas com backoff e uma fila de falhas.
- Identificador de correlação em todos os registros.
- Um alerta para quando a fila de falhas deixar de estar vazia.
São quatro coisas, feitas em dias e não em meses, e são a diferença entre uma integração que te deixa dormir e uma que te obriga a revisar planilhas nas segundas-feiras.
O resto — painéis, métricas, reprocessamento automático — vem depois e só se constrói se essas quatro estiverem lá.