私はScalaでEvent Sourcingを試しています(私はこの2つのフィールドの両方で新しくなっています)。Scalaと不変オブジェクトによるイベントソーシング:効率的ですか?
私は可能な限り不変なものをすべて集めておきたいと思います。 ベースとして、私はESとCQRS(https://github.com/gregoryyoung/m-r、C#で実装されています)のグレッグヤングの例と、このコードをScalaに '翻訳'しています。私の集計のルーツは不変なので、特定のエンティティの各イベントのために、新しいオブジェクトが作成され
:
質問は、イベント・ストアからのオブジェクトの再生についてです。たとえば、100個のイベントを持つエンティティを再生成するには、このエンティティの100個のインスタンスを作成し、最後のインスタンスを最終状態にする必要があります。
オーバーヘッドが効率的かオーバーヘッドが大きいですか?
(私はスナップショットを保存するので、再生する最大イベントは100と思う)ここで
は私のコードです:集計
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
...
}
製品の集計
ためイベント特色
trait Event {
}
基底クラス
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) } ... }
ここでの回答はあまり一般的ではありません。いつものように、あなたのコードをベンチマークし、あまりにもオーバーヘッドかどうかを確認してください。そうであれば、ホットパスを見つけて、可能な限り割り当てを最小限に抑えてください。 –