Я экспериментирую с Event Sourcing с Scala (я новичок и в этих двух областях).Event Sourcing с Scala и неизменяемыми объектами: эффективен ли он?
Я хотел бы сохранить все как можно более неизменными, включая совокупные корни. В качестве базы я следую примеру Грега Янга ES и CQRS (https://github.com/gregoryyoung/m-r, реализованному на C#) и «перевод» этого кода в Scala.
Вопрос о регенерации объекта из хранилища событий:
Поскольку мои агрегатные корни неизменны, для каждого события конкретного объекта, новый объект создается. Так, например, для восстановления объекта, который имеет 100 событий, 100 экземпляров этого объекта должны быть созданы, а последний экземпляр будет конечным.
Является ли это эффективным или слишком накладным?
(Я думаю, что максимальное количество событий для восстановления будет 100, так как я буду хранить моментальные снимки).
Вот мой код:
черта события
trait Event {
}
Базовый класс для агрегатов
abstract class AggregateRoot {
...
// HERE ENTITY IS REGENERATED FROM EVENTS AND EACH TIME NEW INSTANCE IS CREATED FOR EACH ENTITY
def loadFromHistory(history: Seq[Event]): AggregateRoot = {
var aggregate = this
history.foreach(e => aggregate = applyChange(e, false))
aggregate
}
def applyChange(event: Event, isNew: Boolean): AggregateRoot
...
}
продукт Совокупный
case class Product(id: Long, name: String, status: Int, uncommittedChanges: Seq[Event]) extends AggregateRoot {
def changeName(name: String): Product = {
applyChange(ProductNameChangedEvent(id = this.id, name = name))
}
def applyChange(event: Event, isNew: Boolean = true): Product = {
val changedProduct = event match {
case e: ProductCreatedEvent => applyChange(e)
case e: ProductNameChangedEvent => applyChange(e)
case _ => throw new Exception("No event applier")
}
// ALSO HERE I'M COPING ALL THE LOCAL (NEW) CHANGES (THAT ARE NOT STORED IN EVENT STORE YET)
if (isNew) changedProduct.copy(uncommittedChanges = uncommittedChanges :+ event) else changedProduct
}
def applyChange(event: ProductCreatedEvent): Product = {
this.copy(id = event.id, name = event.name)
}
def applyChange(event: ProductNameChangedEvent): Product = {
this.copy(id = event.id, name = event.name)
}
...
}
Любой ответ здесь будет слишком общим и широким. Как всегда, проверьте свой код, посмотрите, слишком ли это накладные расходы. Если это так, найдите горячие пути и попытайтесь свести к минимуму распределения, где это возможно. –