首页 > 解决方案 > 事件溯源“UNDO”流程中的乐观锁机制

问题描述

我一直在问很多关于事件采购的问题,所以对此表示歉意,但我想从一开始就明确这一点。

设置

| p_key | invoice_id | EmployeeId | Event type        | Version | Data |
|-------|------------|------------|-------------------|---------|------|
| 1     | 12345      | E456       | Invoice_Generated | 1       | JSON |
| 2     | 12345      | E567       | Invoice_Reviewed  | 2       | JSON |
| 3     | 12345      | E456       | Invoice_Paid      | 3       | JSON |
| 4     | 12345      | E142       | Invoice_Comment   | 4       | JSON |
| 5     | 12345      | E412       | Invoice_Comment   | 5       | JSON |
| 6     | 12346      | E999       | Invoice_Paid      | 7       | JSON |
| 7     | 12345      | E456       | Invoice_Refunded  | 8       | JSON |

我假设 invoiceId 是聚合。由于版本号会随着发票的每次更改而增加。

用例:

事件存储包含应用于发票的所有事件,还包含有关哪个员工应用它的信息。在当前场景中,生成、审核、支付发票。有人注意到一些问题发表了一些评论,然后我们决定在退还旧款项之前发布新的付款[正在撤消的事件在历史上更早]。

API调用:

退款/发票/{invoiceid}/{employeeid}

事物的流动

选项1

问题

选项 2:

问题

不确定这是否正确。我们是否应该多次将内容添加到事件流中。

也可以查询事件数据库两次,一次仅使用发票 ID,一次使用发票 ID 和员工 ID

如果我遗漏了什么,或者我的版本风格错误,或者我对聚合的假设是错误的,请告诉我。

标签: javadomain-driven-designmicroservicesevent-sourcingoptimistic-locking

解决方案


我建议在你的脑海中弄清楚几点。

无论您对域模型进行什么更改,您都可能希望使用相同的管道;无论是处理一个新命令,还是撤销一个较早的命令,实际的机制都应该以同样的方式对待。

如果“撤消”是您需要的,那么这应该是您的域模型理解如何做的事情,并且您保存在内存中的数据的形状应该支持这些功能。因此,如果您正在设计一个发票模型,允许您查询其历史记录中的特定事件,那么您的内存表示应该允许您访问这些事件。

性能优化的第一条规则是“不要”,但如果您担心从数据库读取数据的成本,您可以缓存模型的热表示。

如果您想弄清楚关系数据库中的乐观写入,Jonathan Oliver是一个很好的起点。


推荐阅读