Pular para o conteúdo

← Todos os projetos

API de Pedidos e Pagamentos

consistênciaNo ar

O gateway de pagamento avisa duas vezes que o mesmo pedido foi pago. E se a fila cair logo depois do banco confirmar?

Webhooks de pagamento são entregues “pelo menos uma vez” — a repetição faz parte do contrato, não é falha. Cada evento recebido tem o id registrado numa tabela com restrição de unicidade, na mesma transação que aplica o efeito. A segunda entrega colide ali e é descartada; em teste, doze entregas simultâneas do mesmo evento produzem um único efeito.

O segundo problema é que gravar o pedido e publicar o evento na fila são operações em sistemas diferentes, sem transação comum — qualquer ordem pode deixar um dos lados para trás. Com o padrão outbox, o evento é gravado numa tabela do próprio banco junto com o pedido, e um worker separado cuida da publicação:

POST /webhooks/stripe          -- assinatura verificada antes de tudo
BEGIN
  INSERT INTO eventos_processados (evento_id)  -- 2ª entrega colide aqui
  UPDATE pedidos SET status = 'PAGO'
  INSERT INTO outbox (tipo, payload)         -- mesmo commit do pedido
COMMIT

worker: lê outbox → publica no RabbitMQ → marca entregue
consumidor: idempotente, porque a entrega é “pelo menos uma vez”

Troquei a promessa de “entrega exatamente uma vez”, que não existe entre sistemas distribuídos, por “pelo menos uma vez com consumidores idempotentes” — que é como integrações reais funcionam.

  • Java 21
  • Spring Boot 4
  • RabbitMQ
  • Stripe
  • PostgreSQL
  • Testcontainers
  • WireMock