Im developing a bank system that uses event sourcing.
I have an aggregate root named Account:
BankAccount {
private var balance: BigInteger = BigInteger.ZERO
private val transactions = mutableListOf<Transaction>()
private var revision: Long = 0
The Transaction entity:
Transaction(val amount: BigDecimal, status: TransactionStatus) {
val id: UUID = UUID.randomUUID()
var status: TransactionStatus = TransactionStatus.REGISTERED
Register a new transaction in bankAccount aggregate root is very simple, but I also have to confirm or to cancel the transaction after some asynchronous validation.
The problem starts when I need to fetch the registered transaction in order to change it state:
fun completeTransaction(transactionId: UUID, newStatus: TransactionStatus){
val transaction = transactions.first { it.id == transactionId }
transaction.changeStatus(newStatus)
}
First problem: Searching the transaction could impact performance given the number of transactions in the list.
In order to solve that, I can implement a snapshot solution, but how to garantee that the list of transaction will have the transaction with status REGISTERED that needs to change status in order to complete it? Because I cant pass the entire list to every snapshot. Its not performatic
Im thinking in transform the Transaction entity to a Transaction Aggregate Root instead. Then my stream will be very short. Use the bankaccount AR to validate balance and a Transaction AR to validate transaction state.
SOLVED
I change the implementation of completeTransaction
function. Everytime a transaction is completed I remove the transaction from the list. So now I can always save the transaction list in the snapshot because it will always contains only UNCOMPLETED transactions