作为一个执着的演员
AKKA Persistent Actor
1 - Can someone explain, why in AKKA Persistent Actors, updating the
state is done after its event is recorded ?
1.1 - What would happen if before the update state "callback" happen, the system crash ?
(我想我有点明白了,但我的困惑来自于我无法理解 Command 的处理方式。我不将其视为不同于处理 Event。见下文)
2 - Is there a difference between the execution/handling of a Command
and the "update state callBack" which is to be related to the handling
of an event.
2.1 - In other words, where should go the handling of the Command, and where should go the handling of the event. Are those two "handlings"
necessarily different.
我看到的所有示例大多表明,除了验证命令然后持久化其关联事件并相应地更新 actor 状态之外,处理命令没有什么特别的。
这意味着处理命令毕竟有点处理事件。这意味着无法记录通风口
我的困惑在于,一个事件只能记录已经发生的事情。但是在我看到的所有示例中,在收到命令后,没有什么特别的事情发生,如果只是实际上,设置执行操作的事件(哪个?)然后更新状态。这多少有点颠倒了事情的逻辑。
如果命令是创建订单,那么我们可能会在验证之后自动创建一个 order_was_created,然后在更新状态函数之后根据事件更新参与者的状态收到。
就是觉得奇怪。因此,从某种意义上说,一个命令除了被验证之外,永远不会触发任何东西,尤其是当它与更新某些东西有关时,但会放置一个事件,然后触发真正的工作。
So a Command is here to simply say if an event as happened, where this
event will actually made a reality after. That is, it is done after for recovery purpose.
令人困惑
命令是更改数据的请求。事件是应用的更改,并且是在事后发生的。在记录事件之前验证数据更改。记录的事件被认为是有保证的成功更新,因为它在应用验证后会持续存在。当持久性 actor 重新水合时,它会重放所有更改并相应地更新状态,并保证可以应用所有更新。这就是事后应用state的根本原因。您看到的模式称为事件溯源。我认为这个 presentation 解释得很好。
最近(2016 年 12 月)的文章“Akka event sourcing done right " by Filippo De Luca 提出了通常工作流程的替代方案,它(通常工作流程)是:
The persistent actor flow looks like this usually:
- A Command is Received by the Actor
- The Command is translated in an Event based on the Actor status.
- The Event is persisted
- The Actor status is modified in response to the event
This flow has a major drawback in the 2nd step. If the logic of translating this Command (or the Stimulus) is bugged the original intention is lost.
但 Filippo 提供了另一种观点:
In the application I am working at the moment, a persistent Actor is responding to some external events received from a bunch of Kafka topics. These events are transformed into local events before persisting them. This transformation, that depends on the current Actor status, contains a lot of business rules that can change in the future.
A bug in this logic makes the whole event sourcing architecture pointless.
I think that a much better model is to apply this logic after the event has been persisted:
- A Command is Received by the Actor
- The Command is persisted
- The Command is applied to the Actor status, that is modified.
What I am proposing is to drop the 2nd step completely and treat the external Command as an Event, storing it in the Journal. In this case, even if we have a bug in the code that applies the command to the status, we can fix it and, it will be applied retroactively
但是,Renato Cavlacanti 评论
In the context of CQRS, a Domain Event is NOT a stimulus. It only express that something have happened that has some business value for your Domain.
An Event can be interpreted and trigger some other actions. In that case, it can be seen as a stimulus, but it's not it's first intent.
Regarding the idea of Command Sourcing, it can be done but it's applicability is limited. The main reason being that the command handlers must be pure. There must be no side effect, no remote calls, no IO, no nothing. Just pure function call against your aggregate data. This is because you want to re-play them and get the same results.
Filippo 认识:
You got the point: in our scenario most of the Commands are actually Events sent by another service. We store them and then we apply changes to our model. The way we apply the changes may vary depending of the business requirement. But of course they cannot be rejected and need to be persisted anyway.
I agree they are not Commands, they are external Events.
I also would say we may want to reject a Command instead (and we do) without persisting anything.
1 - Can someone explain, why in AKKA Persistent Actors, updating the state is done after its event is recorded ?
1.1 - What would happen if before the update state "callback" happen, the system crash ?
(我想我有点明白了,但我的困惑来自于我无法理解 Command 的处理方式。我不将其视为不同于处理 Event。见下文)
2 - Is there a difference between the execution/handling of a Command and the "update state callBack" which is to be related to the handling of an event.
2.1 - In other words, where should go the handling of the Command, and where should go the handling of the event. Are those two "handlings" necessarily different.
我看到的所有示例大多表明,除了验证命令然后持久化其关联事件并相应地更新 actor 状态之外,处理命令没有什么特别的。
这意味着处理命令毕竟有点处理事件。这意味着无法记录通风口
我的困惑在于,一个事件只能记录已经发生的事情。但是在我看到的所有示例中,在收到命令后,没有什么特别的事情发生,如果只是实际上,设置执行操作的事件(哪个?)然后更新状态。这多少有点颠倒了事情的逻辑。
如果命令是创建订单,那么我们可能会在验证之后自动创建一个 order_was_created,然后在更新状态函数之后根据事件更新参与者的状态收到。
就是觉得奇怪。因此,从某种意义上说,一个命令除了被验证之外,永远不会触发任何东西,尤其是当它与更新某些东西有关时,但会放置一个事件,然后触发真正的工作。
So a Command is here to simply say if an event as happened, where this event will actually made a reality after. That is, it is done after for recovery purpose.
令人困惑
命令是更改数据的请求。事件是应用的更改,并且是在事后发生的。在记录事件之前验证数据更改。记录的事件被认为是有保证的成功更新,因为它在应用验证后会持续存在。当持久性 actor 重新水合时,它会重放所有更改并相应地更新状态,并保证可以应用所有更新。这就是事后应用state的根本原因。您看到的模式称为事件溯源。我认为这个 presentation 解释得很好。
最近(2016 年 12 月)的文章“Akka event sourcing done right " by Filippo De Luca 提出了通常工作流程的替代方案,它(通常工作流程)是:
The persistent actor flow looks like this usually:
- A Command is Received by the Actor
- The Command is translated in an Event based on the Actor status.
- The Event is persisted
- The Actor status is modified in response to the event
This flow has a major drawback in the 2nd step. If the logic of translating this Command (or the Stimulus) is bugged the original intention is lost.
但 Filippo 提供了另一种观点:
In the application I am working at the moment, a persistent Actor is responding to some external events received from a bunch of Kafka topics. These events are transformed into local events before persisting them. This transformation, that depends on the current Actor status, contains a lot of business rules that can change in the future.
A bug in this logic makes the whole event sourcing architecture pointless.I think that a much better model is to apply this logic after the event has been persisted:
- A Command is Received by the Actor
- The Command is persisted
- The Command is applied to the Actor status, that is modified.
What I am proposing is to drop the 2nd step completely and treat the external Command as an Event, storing it in the Journal. In this case, even if we have a bug in the code that applies the command to the status, we can fix it and, it will be applied retroactively
但是,Renato Cavlacanti 评论
In the context of CQRS, a Domain Event is NOT a stimulus. It only express that something have happened that has some business value for your Domain.
An Event can be interpreted and trigger some other actions. In that case, it can be seen as a stimulus, but it's not it's first intent.Regarding the idea of Command Sourcing, it can be done but it's applicability is limited. The main reason being that the command handlers must be pure. There must be no side effect, no remote calls, no IO, no nothing. Just pure function call against your aggregate data. This is because you want to re-play them and get the same results.
Filippo 认识:
You got the point: in our scenario most of the Commands are actually Events sent by another service. We store them and then we apply changes to our model. The way we apply the changes may vary depending of the business requirement. But of course they cannot be rejected and need to be persisted anyway.
I agree they are not Commands, they are external Events.
I also would say we may want to reject a Command instead (and we do) without persisting anything.