>
Marcha AJUDA

Como evitar processar o mesmo webhook duas vezes?

Não tente impedir a entrega duplicada, ela é esperada em qualquer sistema de webhook. O que você controla é o efeito: processe cada evento de forma idempotente, de modo que receber o mesmo evento duas vezes produza exatamente o mesmo resultado que recebê-lo uma vez.

A duplicidade aparece por caminhos previsíveis. Seu endpoint processou o evento mas demorou a responder e a chamada estourou o tempo limite: para quem enviou, aquilo falhou, e uma nova tentativa é feita. Ou você tem duas instâncias consumindo a mesma fila. Ou alguém reenviou o evento manualmente para investigar um caso. Em todos, o pedido chega de novo com o mesmo conteúdo.

Implementação

  1. Escolha a chave de idempotência: use o identificador do próprio evento, não o identificador da transação. Se a notificação não trouxer um identificador de evento evidente, confira na documentação qual campo cumpre esse papel.
  2. Crie uma tabela de eventos processados com índice único sobre essa chave. A restrição no banco é a proteção real; um SELECT antes do INSERT deixa uma janela de corrida aberta entre os dois comandos.
  3. Grave a chave e aplique o efeito colateral na mesma transação de banco. Se o efeito for externo (e-mail, emissão de nota, liberação de acesso), grave primeiro o registro e dispare o externo a partir de uma fila lida depois do commit.
  4. Se o INSERT falhar por violação da chave única, pare ali e responda sucesso. O evento já foi tratado; repetir não é erro.
  5. Responda rápido e faça o trabalho pesado de forma assíncrona. Resposta lenta vira tempo esgotado, tempo esgotado vira reenvio, e reenvio vira mais carga em cima de um endpoint que já estava lento.
  6. Verifique a autenticidade do evento antes de tudo isso, conforme o método descrito em https://docs.somosmarcha.com/.

O que costuma dar errado

  • Usar o identificador da transação como chave de idempotência. A mesma transação gera vários eventos legítimos ao longo da vida dela, e você acaba descartando atualizações reais achando que são repetição.
  • Deduplicar em memória, num dicionário ou cache local do processo. Um deploy, um reinício ou uma segunda instância derrubam a proteção. A chave precisa viver em armazenamento compartilhado e persistente.
  • Supor ordem de chegada. Eventos podem chegar fora de sequência. Antes de gravar, compare com o estado que você já tem e não deixe um evento antigo sobrescrever um mais recente.
  • Responder erro para um tipo de evento que você ainda não implementou. Isso tende a provocar novas tentativas de entrega. Registre o evento, responda sucesso e trate depois.
  • Confiar apenas no conteúdo do webhook para liberar produto ou acesso. Use o evento como gatilho e confirme o estado pela API antes de agir.

Quando precisar reprocessar um evento de propósito, corrigir um bug que engoliu a notificação, por exemplo, remova ou marque explicitamente a chave correspondente antes. A idempotência foi construída justamente para bloquear esse reprocessamento; ela não vai abrir exceção sozinha.

A política de novas tentativas e o formato do identificador de cada evento são definidos pela integração e descritos na documentação: https://docs.somosmarcha.com/. Se o comportamento que você observa não bater com o que está documentado, chame com os logs em mãos pelo WhatsApp.

Isso respondeu sua pergunta?

Nesta categoria