Di recente ho iniziato a immergermi in CQRS / ES perché potrebbe essere necessario applicarlo sul posto di lavoro. Sembra molto promettente nel nostro caso, poiché risolverebbe molti problemi.
Ho delineato la mia comprensione approssimativa di come un'app ES / CQRS dovrebbe apparire contestualizzata a un caso d'uso bancario semplificato (prelievo di denaro).
Riassumendo, se la persona A ritira del denaro:
- viene emesso un comando
- il comando viene consegnato per la convalida / verifica
- un evento viene inviato a un archivio eventi se la convalida ha esito positivo
- un aggregatore dequeues l'evento per applicare modifiche sull'aggregato
Da quello che ho capito, il registro degli eventi è la fonte della verità, in quanto è il registro di FATTI, possiamo quindi ricavarne qualsiasi proiezione.
Ora, ciò che non capisco, in questo grande schema di cose, è ciò che accade in questo caso:
- regola: un saldo non può essere negativo
- la persona A ha un saldo di 100e
- la persona A emette un comando di prelievo di 100e
- la convalida passa e viene emesso l'evento MoneyWithdrewEvent of 100e
- nel frattempo, la persona A emette un altro comando Prelievo di 100e
- il primo MoneyWithdrewEvent non è stato aggregato, quindi passa la convalida, poiché il controllo di convalida rispetto all'aggregato (che non è stato ancora aggiornato)
- MoneyWithdrewEvent of 100e viene emesso un'altra volta
==> Siamo in uno stato incoerente di un saldo a -100e e il registro contiene 2 MoneyWithdrewEvent
A quanto ho capito, ci sono diverse strategie per affrontare questo problema:
- a) inserire l'ID della versione aggregata insieme all'evento nell'archivio eventi, quindi se si verifica una mancata corrispondenza della versione in caso di modifica, non accade nulla
- b) utilizzare alcune strategie di blocco, il che implica che il livello di verifica deve in qualche modo crearne uno
Domande relative alle strategie:
- a) In questo caso, il registro eventi non è più la fonte della verità, come gestirla? Inoltre, siamo tornati al client OK mentre era totalmente sbagliato consentire il prelievo, è meglio in questo caso utilizzare i blocchi?
- b) Locks == deadlocks, hai qualche idea sulle migliori pratiche?
Nel complesso, la mia comprensione è corretta su come gestire la concorrenza?
Nota: capisco che la stessa persona che preleva due volte i soldi in così poco tempo è impossibile, ma ho preso un semplice esempio, per non perdersi nei dettagli