Pular para o conteúdo

apps/service-design/transaction-script

170 · Padrões de Design de Serviço · ≈ 5 min de estudo

Transaction Script

Cada caso de uso é um procedimento só, lido de cima a baixo: trava as linhas, valida, move e registra, dentro de uma transação do banco. Não há agregado, Value Object nem evento — a regra mora na função, como if. Use em operações isoladas, cuja regra não se repete em outros casos de uso; quando várias operações compartilham as mesmas invariantes, o caso pede Domain Model.

passos
5
arquivos
3
testes
0
tecnologias
5
Infraestrutura realTypeScriptBunElysiaPostgreSQLDocker
Baixar cartão

Cenário

O banco digital transfere saldo entre contas próprias. A operação é isolada: nenhuma outra operação reaproveita a regra de saldo desta forma, então um script direto basta. Mesmo simples, precisa ser correta sob concorrência — duas transferências da mesma conta, transferências em sentidos opostos ao mesmo tempo e o reenvio da mesma requisição pelo aplicativo.

Planta

Sequência
10/10
alt[chave ja existe][saldo insuficiente][ok]POST /transfers (transferKey, origem, destino, valor)1moneyTransfer(pool, pedido)2BEGIN3SELECT ... ORDER BY number FOR UPDATE (as duas contas)4INSERT transfers ON CONFLICT (transferKey) DO NOTHING5duplicate6ROLLBACK7UPDATE origem, UPDATE destino, INSERT debito e credito8COMMIT9201, 200 ou 42210ClienteAPI de transferenciasmoneyTransferPostgreSQL
10

10 passos — reproduza para seguir o fluxo

Como funciona

5 passos

Um procedimento por operação de negócio.

Esconde cada passo: lembre antes de tocar para revelar.

  1. 01

    moneyTransfer recusa origem igual ao destino antes de abrir a transação

  2. 02

    As duas contas são travadas num único SELECT ... ORDER BY number FOR UPDATE: A→B e B→A simultâneas travam na mesma ordem e não entram em deadlock

  3. 03

    A transferKey é registrada antes da checagem de saldo: o reenvio de uma transferência concluída responde duplicate, mesmo que o saldo atual não cubra mais

  4. 04

    Saldo insuficiente lança ErrorTransferRefused e o ROLLBACK desfaz o registro — nada fica pela metade

  5. 05

    Débito, crédito e os dois lançamentos do livro-razão (partida dobrada) entram no mesmo COMMIT

Trade-offs

O que se ganha, o que se paga

3 vantagenscada ganho tem um preço3 custos

Vantagens

  • Uma função conta a operação inteira

  • Rápido de escrever para operação isolada

  • Fácil de auditar: a ordem do código é a ordem no banco

Custos

  • Regra repetida entre scripts parecidos

  • Sem lugar único para invariante compartilhada

  • Regra de negócio misturada com SQL

apps/service-design/transaction-script

3 arquivos

src/

  • script_transfer.tsO script moneyTransfer e seus auxiliares: lock ordenado, registro, livro-razão, transação
  • api_transfer.tsRota que valida o formato e chama o script

sql/

  • 01_schema.sqlschemaContas, transferências com chave única e lançamentos

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
  5. bun run test# integração contra o serviço real
Requisitos
BunDocker
Sobe junto
PostgreSQL

Por que se relacionam

Teste rápido

Qual destes combina com Transaction Script?

Próximo projeto · Padrões de Design de ServiçoState
Esc

↑ ↓ navegarEnter abrir191 resultados