Recentemente, comecei a mergulhar no CQRS / ES porque talvez eu precise aplicá-lo no trabalho. Parece muito promissor no nosso caso, pois resolveria muitos problemas.
Esbocei meu entendimento aproximado de como um aplicativo ES / CQRS deve parecer contextualizado para um caso de uso bancário simplificado (retirada de dinheiro).
Para resumir, se a pessoa A retirar algum dinheiro:
- um comando é emitido
- comando é entregue para validação / verificação
- um evento é enviado para um armazenamento de eventos se a validação for bem-sucedida
- um agregador remove da fila o evento para aplicar modificações no agregado
Pelo que entendi, o registro de eventos é a fonte da verdade, como é o registro de FACTS, e então podemos derivar qualquer projeção.
Agora, o que eu não entendo, neste grande esquema de coisas, é o que acontece neste caso:
- regra: um saldo não pode ser negativo
- a pessoa A tem um saldo de 100e
- A pessoa A emite um WithdrawCommand de 100e
- a validação passa e o evento MoneyWithdrewEvent of 100e é emitido
- Enquanto isso, a pessoa A emite outro WithdrawCommand de 100e
- o primeiro MoneyWithdrewEvent ainda não foi agregado, portanto, a validação passa, porque a verificação de validação em relação ao agregado (que ainda não foi atualizada)
- MoneyWithdrewEvent of 100e é emitido outra vez
==> Estamos em um estado inconsistente de um saldo de -100e e o log contém 2 MoneyWithdrewEvent
Pelo que entendi, existem várias estratégias para lidar com esse problema:
- a) coloque o ID da versão agregada junto com o evento no armazenamento de eventos, para que, se houver uma incompatibilidade de versão na modificação, nada aconteça
- b) use algumas estratégias de bloqueio, o que implica que a camada de verificação deve, de alguma forma, criar uma
Perguntas relacionadas às estratégias:
- a) Nesse caso, o log de eventos não é mais a fonte da verdade, como lidar com isso? Além disso, retornamos ao cliente OK, considerando que era totalmente errado permitir a retirada, é melhor neste caso usar bloqueios?
- b) Bloqueios == impasses, você tem alguma ideia sobre as melhores práticas?
No geral, meu entendimento está correto sobre como lidar com a simultaneidade?
Nota: Entendo que a mesma pessoa que sacar duas vezes o dinheiro em uma janela de tempo tão curta é impossível, mas tomei um exemplo simples, para não me perder nos detalhes