Pular para o conteúdo

apps/patterns/pg-pool-manager

023 · Padrões Fundamentais · ≈ 5 min de estudo

PG Pool Manager

Um único pg.Pool por processo, com transação que sempre faz COMMIT ou ROLLBACK e sempre devolve a conexão, lock pessimista em ordem determinística e retry da transação inteira em deadlock (40P01). Use em toda escrita de saldo sobre PostgreSQL que precisa ser atômica sob concorrência.

passos
6
arquivos
7
teste
1
tecnologias
4
Infraestrutura realTypeScriptBunPostgreSQLDocker
Baixar cartão

Cenário

Um core bancário transfere R$ 250,00 da conta ACC-001 (R$ 1.000,00) para a ACC-002 (R$ 500,00). Em seguida tenta transferir R$ 5.000,00 da ACC-002: o saldo não cobre e tudo é desfeito. Por fim, 20 transferências opostas de R$ 1,00 disparam ao mesmo tempo: os locks em ordem de id enfileiram as transações em vez de travá-las, e o relatório SERIALIZABLE mostra o total de R$ 1.500,00 conservado.

Planta

Sequência
12/12
alt["erro 40P01 (deadlock)"]alt["sucesso"]["erro"]transferExecute(ACC-001 para ACC-002)1tentativa 12pool.connect() e BEGIN3SELECT ... ORDER BY id FOR UPDATE nas duas contas4compara saldo e valor como NUMERIC5débito, crédito e INSERT em transfers6COMMIT7ROLLBACK8client.release() no finally9espera com backoff exponencial e full jitter10tentativa seguinte, a transação inteira11id da transferência ou erro12demo.tstransactionRetrytransactionExecutePostgreSQL
12

12 passos — reproduza para seguir o fluxo

  1. 01

    Pool únicopoolCreate cria o pg.Pool com max, idleTimeoutMillis e connectionTimeoutMillis, e escuta o error de cliente ocioso

  2. 02

    TransaçãotransactionExecute faz BEGIN, callback, COMMIT; ROLLBACK no erro e client.release() no finally

  3. 03

    Lock ordenadoSELECT ... ORDER BY id FOR UPDATE trava as duas contas sempre na mesma ordem, então transferências opostas não entram em deadlock

  4. 04

    Saldo sob o lockA comparação NUMERIC >= NUMERIC roda no PostgreSQL, depois do lock; centavos inteiros no processo, nunca float de reais

  5. 05

    Retry em deadlocktransactionRetry repete a transação inteira só no 40P01, até 3 tentativas, com backoff exponencial, teto e full jitter

  6. 06

    Leitura consistente e shutdownO relatório usa SERIALIZABLE READ ONLY; SIGTERM drena o pool com pool.end()

apps/patterns/pg-pool-manager

7 arquivos

sql/

  • 01_schema.sqlschemaTabelas accounts e transfers, com as duas contas do cenário

src/

  • pool_bank.tsPool, transação com rollback e release garantidos, retry em deadlock, shutdown
  • transfer_account.tsTransferência com lock ordenado e relatório SERIALIZABLE
  • config_account.tsLê e valida o ambiente no boot
  • transfer_account.test.tstesteIntegração contra PostgreSQL real: rollback, fronteira do saldo, release, concorrência e deadlock
  • demo.tsdemoTransferência confirmada, transferência recusada e corrida de transferências opostas

./

  • docker.shinfraSobe o PostgreSQL com o schema

Executar · com Docker

  1. ./docker.sh up# sobe PostgreSQL
  2. cp .env.example .env# variáveis de ambiente
  3. bun install# dependências
  4. bun run demo# roda o cenário

Testes: bun run test.

Requisitos
BunDocker
Sobe junto
PostgreSQL

Por que se relacionam

Teste rápido

Qual destes combina com PG Pool Manager?

Próximo projeto · Padrões FundamentaisProcess Orchestrator
Esc

↑ ↓ navegarEnter abrir191 resultados