Domain driven design 偶尔连接的CQRS系统
问题: 两名员工(A&B)在编辑customer#123(比如版本#20)时同时下线,而在下线时继续进行更改 场景: 1-两名员工编辑customer#123并更改一个或多个相同的属性 2-两名员工编辑customer#123,但不进行相同的更改(他们相互交叉而不接触) 。。。然后他们都在线返回,首先是员工A追加,从而将客户更改为版本21,然后是员工B,仍然是版本20 问题: 在场景1中,我们要保留哪些更改 我们可以在场景2中进行合并吗 上下文: 1-CQRS+事件来源风格系统 2-将事件源数据库用作队列 3-读取模型的最终一致性 4-RESTful API 编辑-1:根据迄今为止的答案进行澄清: 为了执行细粒度的合并,我需要对表单中的每个字段使用一个命令,例如 上面,针对ChangeName、ChangeSupplier、ChangeDescription等的细粒度命令,每个命令都有自己的时间戳,允许在A和B都更新了ChangedName的情况下自动合并 编辑-2:根据特定事件存储的使用情况进行跟进: 似乎我将使用@GetEventStore来持久化我的事件流 它们使用乐观并发,如下所示:Domain driven design 偶尔连接的CQRS系统,domain-driven-design,cqrs,event-sourcing,eventstoredb,occasionallyconnected,Domain Driven Design,Cqrs,Event Sourcing,Eventstoredb,Occasionallyconnected,问题: 两名员工(A&B)在编辑customer#123(比如版本#20)时同时下线,而在下线时继续进行更改 场景: 1-两名员工编辑customer#123并更改一个或多个相同的属性 2-两名员工编辑customer#123,但不进行相同的更改(他们相互交叉而不接触) 。。。然后他们都在线返回,首先是员工A追加,从而将客户更改为版本21,然后是员工B,仍然是版本20 问题: 在场景1中,我们要保留哪些更改 我们可以在场景2中进行合并吗 上下文: 1-CQRS+事件来源风格系统 2-将事件源数据
- 流中的每个事件使流版本增加1
- 写入可以使用写入程序上的ES ExpectedVersion标头指定预期版本
- -1指定流不应该已经存在
- 0及更高版本指定流版本
- 如果流不在版本中,则写入将失败,您可以使用新的预期版本号重试,或者重新处理该行为,并决定如果您选择这样做,则写入将失败
- 如果未指定预期版本,则禁用乐观并发控制
- 在此上下文中,乐观并发性不仅基于消息ID,还基于事件#
- 客户在v20
- A处于脱机状态,根据v20的过时模型编辑更改
- B处于脱机状态,根据v20的过时模型编辑更改
- A联机,批处理发送一个排队的
命令,v20的客户被加载并作为v21持久化ChangeName
- B联机,batch发送一个排队的
命令,v21的客户被加载并作为v22持久化ChangeAddress
- 数据库包含的用户具有正确的名称和地址,如预期的那样 在场景1中,使用此设置,两名员工将覆盖其他员工的更改:
- 客户在v20
- A处于脱机状态,根据v20的过时模型编辑更改
- B处于脱机状态,根据v20的过时模型编辑更改
- A联机时,batch向“John Doe”发送一个排队的
命令,v20的客户被加载并持久化为名为“John Doe”的v21ChangeName
- B联机时,batch向“Joan d'Arc”发送排队的
命令,v21(名为“John Doe”)的客户被加载并持久化为v22(名为“Joan d'Arc”)ChangeName
- 数据库包含名为“Joan d'Arc”的用户 如果B在A之前在线,则反之亦然:
- 客户在v20
- A处于脱机状态,根据v20的过时模型编辑更改
- B处于脱机状态,根据v20的过时模型编辑更改
- B联机时,batch向“Joan d'Arc”发送排队的
命令,v20的客户被加载并持久化为v21(名称为“Joan d'Arc”)ChangeName
- 当A联机时,batch向“John Doe”发送排队的
命令,v21的客户被加载并持久化为名为“John Doe”的v22ChangeName
- 数据库包含名为“John Doe”的用户 有两种方法可以启用冲突检测:
- 检查命令的创建日期(即员工修改的时间)是否在
客户的上次修改日期之后。这将禁用场景2的自动合并功能,但会
- 以下是一些解决方案的一般概述:
情景1
必须有人来决定,最好是人。您应该询问用户或表明存在冲突
Dropbox通过拾取后面的文件并将file.conflict文件保留在同一目录中供用户删除或使用来解决此问题
情景2
保留原始数据,查看哪些字段实际发生了更改。然后,您可以应用员工1的更改,然后再应用员工2的更改,而无需任何干预
场景3(仅当更改在不同时间上线时)
让第二个用户知道他们脱机时发生了更改。尝试场景2并向第二个用户显示新结果(因为这可能会更改他的输入)。然后询问他是否要保存更改、先修改更改或将其丢弃。如果我正确理解了您的设计图,则偶尔连接的用户会将命令(即更改请求)排队,当用户重新连接时,排队的命令会一起发送;只有一个数据库权限(命令处理程序查询该权限以加载其aggretate的最新版本);只有视图模型与客户端同步 在此设置中,场景2由您的设计自动合并,如果您明智地选择了命令,请阅读:使它们细粒度化:对于每个可能的更改,选择一个命令。然后,在客户端重新连接时,命令按任意顺序处理,但由于它们只影响不相交字段,因此没有问题: