我在寻找一种审计模式来保存我的实体的历史,然后我遇到了事件溯源模式。这是一个有趣的模式,其中大部分对我来说都很有意义,但我有一个关于如何实现特定用例场景的问题?
用例:
- 已生成金额为 100 美元且状态为审核中的发票。
- 然后发票状态更新为billed
- 然后支付 50 美元,调整 20 美元,状态更新为已支付
- 我们后来意识到金额不正确。所以我们想回滚之前的交易并将账单状态恢复为重新开单
- 然后我们将支付 70 美元并调整 20 美元并更新发票状态以完成。
以我对事件存储的理解。它应该只包含应用于实体的操作。因此事件始终具有更新的交易金额(付款和调整)和状态。
数据库:
发票:
| id | balance | payment | adjustment | status |
|-------|---------|---------|------------|----------|
| 12345 | 10 | 70 | 20 | Paid |
事件商店:
| event_id | invoice_id | Event | Payload |
|----------|------------|------------------|---------|
| 1 | 12345 | Invoice_InReview | JSON |
| 2 | 12345 | Invoice_Billed | JSON |
| 3 | 12345 | Invoice_Paid | JSON |
| 4 | 12345 | Invoice_Reversed | JSON |
| 5 | 12345 | Invoice_Paid | JSON |
JSON 包含有关付款、调整和状态更改的信息
这是我的问题
- 我知道余额是如何反转的,但我不知道我们如何才能对状态实现同样的效果
- 另外,如果 api 调用(命令)因上述事件发生故障,我将如何处理。 IE
- 第 3 步调用服务
- 然后是第5步
- 然后是第 4 步。
据我所知,余额没有问题,但发票状态不正确。
请告诉我如何最好地处理事件溯源模式。
最佳答案
I get how balances can be reversed but I do not see how we can accomplish the same effect for status
因此,首先要做的是与您的领域专家核实,以了解通用语言是否具有发票状态在冲销和还款之间的概念。
根据我在此处看到的情况,我预计会发生逆转,从而使状态再次变为已结算。我们认为它已支付,但该条目是错误的,因此我们会将对象恢复到之前的状态。
如果那是正确的,那么我们的状态将是Billed
。
但它可能不是——这不是撤消,而是您域中的一种行为。这可能会将域移动到状态机以前未发现的部分。
how will I handle if api calls(commands) come out of order for the above events.
那里可能隐藏着两个不同的问题 - 我将对每个问题进行总结。
如果您担心下游消费者对事件的 react ,那么设计您的消费者很重要——如果他们需要了解整个历史,那么他们会从历史中读取。对历史变化使用react的消费者将从事件存储中读取有序历史,而不是对出现在消息传输中的消息使用react。换句话说,发布的事件就像一个通知,告诉消费者刷新其历史副本。
如果您担心如果命令出现乱序会得到“错误”的历史记录,那么您需要阅读并整合 Udi Dahan 的文章 Race Conditions Don't Exist
A microsecond difference in timing shouldn’t make a difference to core business behaviors.
关于java - 在均匀采购模式中处理状态更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49944789/