Pular para o conteúdo

apps/data-patterns/inbox-pattern

081 · Dados & Persistência · ≈ 5 min de estudo

Inbox Pattern

O lado receptor grava toda mensagem recebida numa tabela inbox antes de processar, com a chave do remetente como única. A entrega duplicada é absorvida na porta, e um processador separado aplica cada mensagem uma vez só, na mesma transação que a marca como concluída. É o par do Outbox: a entrega é at-least-once, o efeito é exactly-once.

passos
5
arquivos
6
teste
1
tecnologias
5
Infraestrutura realTypeScriptBunElysiaPostgreSQLDocker
Baixar cartão

Cenário

Banco digital recebe do PSP as notificações de PIX creditados nas contas. O PSP reenvia quando não recebe confirmação a tempo, então o mesmo PIX pode chegar várias vezes. O crédito na conta precisa acontecer uma vez só, e um PIX para conta inexistente não pode travar os outros.

Planta

Sequência
9/9
notificação PIX (end_to_end_id E1)1INSERT inbox_messages ON CONFLICT DO NOTHING22023mesma notificação E1 (retentativa)4conflito na chave única, nada gravado5202 duplicate: true6BEGIN, SELECT pending FOR UPDATE SKIP LOCKED7credita a conta, grava pix_credits, marca done8COMMIT9falha no crédito: volta ao savepoint, registra erro e backoff; no limite, failedPSPAPI da inboxPostgreSQLProcessador
9

9 passos — reproduza para seguir o fluxo

Como funciona

5 passos

Deduplica mensagens na entrada.

Esconde cada passo: lembre antes de tocar para revelar.

Vocabulário compartilhado

  1. 01

    A API grava a notificação em inbox_messages com end_to_end_id único e responde 202 na hora — reentrega vira duplicate: true, sem segunda mensagem

  2. 02

    O processador pega uma mensagem pending por vez com FOR UPDATE SKIP LOCKED: vários processadores dividem a fila sem pegar a mesma

  3. 03

    Crédito na conta, registro em pix_credits e status = 'done' commitam juntos; queda no meio desfaz os três

  4. 04

    Falha no crédito volta ao savepoint, registra last_error e agenda nova tentativa com backoff exponencial

  5. 05

    Ao atingir INBOX_ATTEMPTS_MAX a mensagem vira failed e sai do caminho das outras

Trade-offs

O que se ganha, o que se paga

3 vantagenscada ganho tem um preço3 custos

Vantagens

  • Reentrega absorvida na porta

  • Crédito e conclusão atômicos

  • Vários processadores sem coordenação

Custos

  • Crédito acontece depois, não na resposta

  • Polling adiciona latência de segundos

  • Tabela cresce: exige limpeza de done

apps/data-patterns/inbox-pattern

6 arquivos

sql/

  • 01_schema.sqlschemaaccounts, inbox_messages com chave única do remetente, pix_credits

src/

  • api_inbox.tsRecebe a notificação e grava na inbox
  • processor_inbox.tsProcessa com SKIP LOCKED, savepoint, backoff e failed
  • demo.tsdemoEntregas, reentrega, conta inexistente e processamento
  • processor_inbox.test.tstesteDedup, reprocessamento, falha isolada e concorrência contra PostgreSQL real

src/config_inbox.ts / src/

  • pool_inbox.tsAmbiente validado, pool e transactionExecute

Executar · com Docker

  1. ./docker.sh up# sobe PostgreSQL
  2. bun install# dependências
  3. bun run demo# roda o cenário
  4. bun run test# integração contra o serviço real

Serviços separados: bun run api e bun run processor.

Requisitos
BunDocker
Sobe junto
PostgreSQL

Por que se relacionam

Teste rápido

Qual é o próximo passo depois de Inbox Pattern?

Próximo projeto · Dados & PersistênciaDatabase per Service
Esc

↑ ↓ navegarEnter abrir191 resultados