如何在 CQRS 中处理基于集合的一致性验证?
我有一个相当简单的域模型,涉及 Facility
聚合根列表。鉴于我使用 CQRS 和事件总线来处理从域引发的事件,您如何处理集合的验证?例如,假设我有以下要求:
Facility
必须具有唯一的名称。
由于我在查询端使用最终一致的数据库,因此在事件处理器或处理事件时不能保证其中的数据是准确的。
例如,FacilityCreatedEvent
位于查询数据库事件处理队列中,等待处理并写入数据库。新的 CreateFacilityCommand 被发送到要处理的域。域服务查询读取数据库以查看是否有任何其他 Facility
已使用该名称注册,但返回 false,因为 CreateNewFacilityEvent
尚未处理和写入到商店。新的 CreateFacilityCommand
现在将成功并抛出另一个 FacilityCreatedEvent
,当事件处理器尝试将其写入数据库并发现另一个 Facility
时,该事件将会爆炸。 code> 已以该名称存在。
I have a fairly simple domain model involving a list of Facility
aggregate roots. Given that I'm using CQRS and an event-bus to handle events raised from the domain, how could you handle validation on sets? For example, say I have the following requirement:
Facility
's must have a unique name.
Since I'm using an eventually consistent database on the query side, the data in it is not guaranteed to be accurate at the time the event processesor processes the event.
For example, a FacilityCreatedEvent
is in the query database event processing queue waiting to be processed and written into the database. A new CreateFacilityCommand
is sent to the domain to be processed. The domain services query the read database to see if there are any other Facility
's registered already with that name, but returns false because the CreateNewFacilityEvent
has not yet been processed and written to the store. The new CreateFacilityCommand
will now succeed and throw up another FacilityCreatedEvent
which would blow up when the event processor tries to write it into the database and finds that another Facility
already exists with that name.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
最终一致性和集验证:
另请参阅此相关问题:使用 CQRS 和事件源时的唯一性验证
Three approaches are outlined in Eventual Consistency and Set Validation:
Also see this related question: Uniqueness validation when using CQRS and Event sourcing
在这种情况下,您可以实现一个简单的 CRUD 样式服务,该服务基本上在具有主键约束的 Sql 表中进行插入。
插入只会发生一次。当具有相同值且只应存在一次的重复命令命中聚合时,聚合调用服务,服务因违反主键约束而导致插入操作失败,抛出错误,整个过程失败且没有事件生成,在查询端没有报告,可能会在表中报告失败,以进行最终一致性检查,用户可以在其中查询以了解命令处理的状态。要检查这一点,只需使用命令 Guid 一次又一次查询命令状态视图模型即可。
显然,当该命令保存的值在进行主键检查的表中不存在时,操作成功。
主键约束表应该仅用作服务,但是,由于您实现了事件源,因此您可以重放事件以重建主键约束表。
In this case, you may implement a simple CRUD style service that basically does an insert in a Sql table with a primary key constraint.
The insert will only happen once. When duplicate commands with the same value that should only exist one time hits the aggregate, the aggregate calls the service, the service fails the Insert operation due to a violation of the Primary Key constraint, throws an error, the whole process fails and no events are generated, no reporting in the query side, maybe a reporting of the failure in a table for eventual consistency checking where the user can query to know the status of the command processing. To check that, just query again and again the Command Status View Model with the Command Guid.
Obviously, when the command holds a value that does not exists in the table for primary key checking, the operation is a success.
The table of the primary key constraint should be only be used as a service, but, because you implemented Event sourcing, you can replay the events to rebuild the table of primary key constraint.
由于唯一性检查会在数据写入之前完成,因此更好的方法是构建一个事件跟踪服务,该服务会在进程完成或终止时发送通知。
Because uniqueness check would be done before data writing, so the better method is to build a event-tracking service, which would send a notification when the process finished or terminated.
我采用的解决方案是添加一个
System
聚合根,它可以维护当前Facility
名称的列表。创建新的Facility
时,我使用System
聚合(只有一个System
作为全局对象/单例)作为它的工厂。如果给定的设施名称已经存在,则会抛出验证错误。这将验证约束保留在域内,并且不依赖于最终一致的查询存储。
The solution I went with was to add a
System
aggregate root that could maintain a list of the currentFacility
names. When creating a newFacility
, I use theSystem
aggregate (only oneSystem
as a global object / singleton) as a factory for it. If the given facility name already exists, then it will throw a validation error.This keeps the validation constraints within the domain and does not rely on the eventually consistent query store.