2
respostas

Como garantir a atomicidade de uma transação quando a implementação é baseada em eventos?

Sei que a dúvida não é relacionada ao domínio, mas sim sobre persistência. De qualquer forma, me bateu essa dúvida aqui.

Se eu tenho eventos sendo publicados e escutados, terei objetos sendo instanciados e/ou alterados. E se a regra de transação, dando um exemplo, for de comittar tudo ou dar rollback, como eu faço para garantir essa transação? Pois se for pra basear no que já estudei, não acredito que seja prudente deixar o pool de conexão aberto para ir carregando ele por cada evento.

Para dar um exemplo fora do praticado na aula, imaginem que eu tenho um pagamento sendo recebido e que deve ser validado. Após a validação, o pagamento recebido vira um Pagamento Efetivado ( daqui pra frente só regra de domínio). O sistema publica um evento de Pagamento Efetivado que é ouvido pelo Gerenciador de Crédito, que publica o Crédito, e é ouvido pelo Gerador de Movimentação Financeira que cria uma NOVA MOVIMENTAÇÃO à partir do crédito publicado. Movimentação financeira também publica essa movimentação, que é ouvida pelo Atualizador de Fatura.

A atomicidade que me refiro, está entre inserir uma nova movimentação e atualizar a fatura. Porém, como são eventos diferentes, ficou difícil pra eu entender como commitar as duas de uma vez (ou dar rollback no processo se uma delas falhar).

  1. Eu deveria carregar a transação no parâmetro? Parece que eu violaria o domínio com informações de infra fazendo isso.
  2. Eu deveria criar uma interface "transacional" para estabelecer um contrato comum entre os casos de uso que devem gerar uma transação única?
  3. Eu deveria utilizar outro padrão em vez do Observer para trabalhar melhor com o nível de atomicidade necessária e com menos dor de cabeça?
  4. Eu deveria criar uma classe chamada "GerenciadorDeTransação" e adicionar cada transação numa lista para, somente no fim do processo, realizar o commit ou rollback? Isso não faria utilizar processamento desnecessário?

Como dá pra perceber, preciso mesmo de ajuda

2 respostas

Ainda continuo com essa dúvida, será que alguém já enfrentou caso parecido?

Olá João, tudo bem?

Entendo sua dúvida e posso te ajudar com algumas sugestões.

Uma opção seria utilizar um mecanismo de controle de transações distribuídas, como o JTA (Java Transaction API), que permite coordenar transações em diferentes sistemas. Dessa forma, você poderia garantir a atomicidade das transações mesmo com a implementação baseada em eventos.

Outra opção seria utilizar um padrão como o Saga Pattern, que permite coordenar transações entre diferentes serviços de forma mais granular, definindo um fluxo de transações que podem ser compensadas em caso de falha.

Sobre suas perguntas específicas, acredito que carregar a transação no parâmetro pode realmente violar o domínio com informações de infraestrutura, e criar uma interface transacional pode ser uma opção interessante para estabelecer um contrato comum entre os casos de uso que devem gerar uma transação única.

Quanto ao uso do padrão Observer, ele pode ser adequado para o seu caso, mas é importante avaliar se ele atende às suas necessidades de atomicidade e consistência.

Não acredito que criar uma classe "GerenciadorDeTransação" e adicionar cada transação numa lista seja a melhor opção, pois isso pode gerar processamento desnecessário e não garantir a atomicidade das transações.

Espero ter ajudado e bons estudos!