多实体聚合最佳实践:何时在 Axon 聚合中创建第一个 "sub" 实体
Multi-Entity Aggregate Best Practices : when to create the first "sub" entity in an Axon Aggregate
(将此讨论从 Axon 论坛移至此处
https://discuss.axoniq.io/t/multi-entity-aggregate-best-practices-when-to-create-the-first-entity/3827)
Axon 文档建议通过 EventSourcingHandler 将新实体添加到聚合中…
来自:Multi-Entity Aggregates - Axon Reference Guide
The creation of the Entity takes place in an event sourcing handler of it’s parent.
It is thus not possible to have a ‘command handling constructor’ on the entity class as with the aggregate root.
(原文:注意“it's”中的撇号是错字)
但是when/where你会创建初始实体吗?
您的 GiftCard 聚合开始时没有任何实体。我们有一个类似的模型,但希望在创建聚合时创建一个初始实体。例如想象一下,如果一张新的 GiftCard 总是带有“默认”GiftCardTransaction。
你会在哪里做这个?
a) 在礼品卡的构造函数中:
public GiftCard(IssueCardCommand cmd) {
...
// problem: never gets replayed!
transactions.add(new GiftCardTransaction(/*defaults*/)
b) 在初始化事件处理程序中
public void on(CardIssuedEvent evt) { // initialize aggregate
// create the first entity
// gets replayed when the aggregate creation is replayed
transactions.add(new GiftCardTransaction(/*defaults*/)
}
c) 在事件处理程序中,但通过触发事件
public void on(CardIssuedEvent evt) { // initialize aggregate
// fire the event to create the first entity
// problem: gets replayed twice: when the aggregate creation is replayed and the subsequent event is replayed!!?
apply(new CardRedeemedEvent(/*defaults*/);
}
d) 与 c 相同,但使用注释来防止双重重放:
public void on(CardIssuedEvent evt) { // initialize aggregate
// call a non-replayable method to fire the event
createFirstEntity();
}
@DisallowReplay
public void createFirstEntity() {
// The replay of this CardRedeemedEvent will create the first entity on replay,
// but the replay of the CardIssuedEvent will not, thanks to the @DisallowReplay... right??
apply(new CardRedeemedEvent(/*defaults*/);
}
Vaishnavi 在 Axon 论坛上回答了这个问题:
Creating the entity should be done using the @EventSourcingHandler, in your example option b. The state changes should happen here, and the first Event Handler should set the Aggregate Identifier. Here’s a reference to the Aggregate documentation.
Hope this helps with the aggregate creation entity.
但我想知道这是否不会混淆来自@EventSourcingHandler 的实体的实例化+添加,用于创建实体 的事件(这确实看起来是正确的),与我的选项 b 在处理程序中为创建 Aggregate
的 事件创建第一个实体的情况
实际上,在仔细阅读文档后,我想知道 c.不是正确答案:
来自:Command Handlers - Axon Reference Guide
Axon will ignore the apply()
invocation when replaying historic events upon sourcing the given Aggregate
这句话的意思是我在c中的注释。关于重播两次的“问题”是错误(Axon 足够聪明,知道事件处理程序中的 apply
总是会导致双重重播,因此在重播时忽略它...?)
c也是。正确答案?
具体来说:
如果您想在多实体聚合中创建初始实体,请在处理 聚合 创建事件的事件(采购)处理程序中创建它
使用事件溯源存储库时,正确答案是 b。您不应在事件溯源处理程序中应用事件。事件源处理程序应该只更新聚合的状态。每次处理新命令时,在命令处理开始之前,将针对该聚合的空实例重播具有该命令的 AggregateId 的所有事件。这就是您不应在 EventSourcing 处理程序中应用事件的原因。实体的创建是第一个事件的副作用。可以在使用 EventHandler 注释的方法或 类 中使用禁止重播,但不能用于 EventSourcingHandlers。
(将此讨论从 Axon 论坛移至此处 https://discuss.axoniq.io/t/multi-entity-aggregate-best-practices-when-to-create-the-first-entity/3827)
Axon 文档建议通过 EventSourcingHandler 将新实体添加到聚合中…
来自:Multi-Entity Aggregates - Axon Reference Guide
The creation of the Entity takes place in an event sourcing handler of it’s parent. It is thus not possible to have a ‘command handling constructor’ on the entity class as with the aggregate root.
(原文:注意“it's”中的撇号是错字)
但是when/where你会创建初始实体吗?
您的 GiftCard 聚合开始时没有任何实体。我们有一个类似的模型,但希望在创建聚合时创建一个初始实体。例如想象一下,如果一张新的 GiftCard 总是带有“默认”GiftCardTransaction。 你会在哪里做这个?
a) 在礼品卡的构造函数中:
public GiftCard(IssueCardCommand cmd) {
...
// problem: never gets replayed!
transactions.add(new GiftCardTransaction(/*defaults*/)
b) 在初始化事件处理程序中
public void on(CardIssuedEvent evt) { // initialize aggregate
// create the first entity
// gets replayed when the aggregate creation is replayed
transactions.add(new GiftCardTransaction(/*defaults*/)
}
c) 在事件处理程序中,但通过触发事件
public void on(CardIssuedEvent evt) { // initialize aggregate
// fire the event to create the first entity
// problem: gets replayed twice: when the aggregate creation is replayed and the subsequent event is replayed!!?
apply(new CardRedeemedEvent(/*defaults*/);
}
d) 与 c 相同,但使用注释来防止双重重放:
public void on(CardIssuedEvent evt) { // initialize aggregate
// call a non-replayable method to fire the event
createFirstEntity();
}
@DisallowReplay
public void createFirstEntity() {
// The replay of this CardRedeemedEvent will create the first entity on replay,
// but the replay of the CardIssuedEvent will not, thanks to the @DisallowReplay... right??
apply(new CardRedeemedEvent(/*defaults*/);
}
Vaishnavi 在 Axon 论坛上回答了这个问题:
Creating the entity should be done using the @EventSourcingHandler, in your example option b. The state changes should happen here, and the first Event Handler should set the Aggregate Identifier. Here’s a reference to the Aggregate documentation.
Hope this helps with the aggregate creation entity.
但我想知道这是否不会混淆来自@EventSourcingHandler 的实体的实例化+添加,用于创建实体 的事件(这确实看起来是正确的),与我的选项 b 在处理程序中为创建 Aggregate
的 事件创建第一个实体的情况实际上,在仔细阅读文档后,我想知道 c.不是正确答案:
来自:Command Handlers - Axon Reference Guide
Axon will ignore the
apply()
invocation when replaying historic events upon sourcing the given Aggregate
这句话的意思是我在c中的注释。关于重播两次的“问题”是错误(Axon 足够聪明,知道事件处理程序中的 apply
总是会导致双重重播,因此在重播时忽略它...?)
c也是。正确答案?
具体来说: 如果您想在多实体聚合中创建初始实体,请在处理 聚合 创建事件的事件(采购)处理程序中创建它
使用事件溯源存储库时,正确答案是 b。您不应在事件溯源处理程序中应用事件。事件源处理程序应该只更新聚合的状态。每次处理新命令时,在命令处理开始之前,将针对该聚合的空实例重播具有该命令的 AggregateId 的所有事件。这就是您不应在 EventSourcing 处理程序中应用事件的原因。实体的创建是第一个事件的副作用。可以在使用 EventHandler 注释的方法或 类 中使用禁止重播,但不能用于 EventSourcingHandlers。