Executando verificação de segurança...
1
Ademir
1 min de leitura ·

Quando usar transactions, melhores praticas

Comecei a trabalhar com nodejs tem mais de um ano e me pego diariamente em conflito com minha mente sobre o uso de transactions com arquitetura limpa. O que acontece é que os ORM do nodejs não fornecem um modo claro de como se trabalhar com transações entre varios arquivos. Os termos "Transação global", "Transação com escopo da requisição", são o que eu venho buscado, porem estou começando a acreditar que talves o modo que eu aprendi a usar transactions (laraboy) que seja errado.
Então a minha duvida é, como vocês utilizam ? Como aprenderam a usar e quais boas praticas recomendam ?

Carregando publicação patrocinada...
1
1

Por exemplo um checkout de pagamento, em que eu salvo no banco algumas tabelas e tambem faço operações com api externa para comfirmar a compra. Como to usando varios arquivos nao consigo fazer a transação cobrir todos os casos de maneira convencional, ate tem como funcionar porem gera acoplamento e sinceramente parece gambiarra. To usando nestjs com typeorm.

1

Acho que vc está confundido conceitos, caro amigo.

neste caso vc não está falando apenas de transaction e sim de resiliencia, como deixar minha operação
resiliente
a falhas.

"Chegou uma compra nova na minha API de checkout, preciso fazer algumas operações para validar a compra e enviar as informações da compra para o usuário"

Primeira cosia que eu faria é salvar no meu banco de dados um novo pedido, independente de qualquer operação externa.

Depois eu emitiria um evento chamado newOrder para minhas apis externas, como estoque, logistica, ERP e tudo mais.

Depois do envio de tais eventos, eu colocaria o status do pedido e mudaria para em processamento,

Aguardaria o retorno de todas as APIs externas via hook ou mensageria, depois da conclusão de todas e minha lógica entender que o produto já foi validado, iria emitir um novo evento OrderSuccess que avisaria o meu usuário que de tudo certo.

Faz sentido para vc?

1

Existem várias aplicações práticas, mas uma que eu gosto muito é quando você está trabalhamdo com threads e podemos pensar em uma entidade para os trabalhos jobs que é populada por tarefas longas a serem executadas no background.

Num cenário hipotético, se você tiver 64 threads rodando em paralelo precisa de alguma forma garantir que não haverá uma race condition - por exemplo: dois ou mais processos pegarem um job e iniciarem a mesma tarefa.

Nesse caso você pode iniciar uma transaction, e fazer um "SELECT FOR UPDATE" na entidade jobs que irá receber um lock até que essa transaction seja resolvida com um COMMIT ou um ROLLBACK. Isso garante que a thread/worker que pegou aquela tarefa faça o UPDATE na entidade atribuindo um PID e finalmente te dá uma forma de um outro processo como watchdog monitorar se o PID ainda está em execução e todo processo dos threads correr de forma organizada.

Mas além dessa aplicação existem várias outras aonde, por exemplo, você tenha regra de negócio entre a Primary Key a Foreign Key e deseje fazer um rollback para não deixar uma entidade orders sem itens (um case bastante comum).

E de maneira bastante ampla existem várias aplicações, mas a regra é simples: se precisou de uma entidade atômica, então requer de uma transaction. Mas se ainda não ficou claro, posso dar outro último exemplo: imagine que seu sistema utilize Redis + Mongo + Postgres ou MySQL (comum em microsserviços), e uma entidade para ser salva no MySQL depende do Redis e do Mongo, você utiliza uma transaction para validar tudo e após inserir corretamente, você COMMITA a transação, se não faz rollback.

Espero ter ficado claro.

1

Entendi mano, de fato. Na teoria acredito que seja esse caminho mesmo, mas na pratica com nodejs com os ORM como typeorm e prisma fica complicado fazer uma implementação mais robusta, que chama varios arquivos e que ta protegida pela transaction. Já se deparou com esse problema ?

1

Como assim implementação mais robusta? Acho que o conceito de transaction é claro em todas as ORM de mercado, vai depender da sua abordagem e do que voce precisa fazer.

1

As transações principalmente em ORM mais maduras, seguem o mesmo protocolo e implementações parecidas. Agora voce falando de DDD, voce pode utilizar tanto no Laravel ou Express as transactions na sua camada de repository infra/repository/meu-banco.

Caso voce precisar criar uma transação que afete mais de uma tabela por exemplo: CreateUserRepository e CreateUserGroupRepository é acho melhor seguir o conceito de responsabilidade única e também a regra do seu projeto. Se o seu usuário precisa de um grupo para existir, voce pode dentro do CreateUserRepository já criar a transação dentro dele.

Caso voce queira abstrair a transação para outra camada, na aplication ou main eu acho over, por que a transação só deveria existir na camanda de repository