CQRS按特定顺序运行处理程序
本文关键字:处理 程序 运行 定顺序 CQRS | 更新日期: 2023-09-27 18:10:04
我有2个处理程序的运行订单删除和重新排序的图片,并希望一些建议的最佳解决方案。
在UI上删除一些图片,用户点击删除按钮。整个流程,delete命令直到实际删除物理文件的事件处理程序被启动。
然后用户立即对剩下的图片进行分类。从重新排序命令到文件系统的重新排序事件处理程序的新流再次触发。
已经存在并发问题。如果不完成删除,则无法正确应用重新排序。目前这个问题是用某种锁来解决的。创建一个临时文件,然后在删除流程结束时删除。当该文件存在时,另一个线程(根据用户操作重新排序或删除)正在等待。
这不是一个理想的解决方案,我想改变它。潜在的解决方案还必须非常快(当然当前的解决方案并不快),因为在排序结束时通过JSON调用更新UI。
在后面的实现中,我们考虑使用事件队列,但目前我们被卡住了。
有任何想法将不胜感激!谢谢你,摩苏!
编辑:我们在客户端使用Javascript数据管理器解决了其他最终的一致性问题。基本上是乐观主义和欺骗用户!:)我开始相信这也是我们要走的路。但是,我如何知道文件系统中的数据何时发生了更改呢?
Max建议是非常受欢迎的,通常它们都适用。
有时很难解释一个实现的所有细节,但有一个细节应该提到:我们存储图片的方式意味着当重新排序时,所有图片的路径(以及所有链接)都会改变。
一个同事认为把这部分去掉是一个很好的主意。这意味着即使顺序改变了,图片的路径也会保持不变。在UI端,在显示顺序中的图片索引和它的路径之间会有一个映射,这意味着不需要再更改文件系统,除非删除。
由于我们希望对用户尽可能的宽容,这对我们来说是最好的解决方案。我认为,一般来说,当出现并发问题时,这也是一种很好的方法。可以删除并发性吗?
对此我有一个看法。你到底要重新订购什么?照片吗?基于,比如说,日期。为什么会有这样的命令?这个命令的结果是每个人都能看到,还是只有这个特定的用户能看到?
我只能猜测,但看起来你这里有一个演示问题。不需要在写端以某种顺序存储图片,它只是一个名称列表和到文件存储的链接。您应该做的是在用户设置或集合设置中存储一个小字段:日期升序或名称降序。所以命令Reorder应该只改变这个小字段。然后,当您加载图库时,应首先读取此字段,并基于此加载一个或另一个视图。因为现在存储很便宜,你可以为你需要的每一个排序参数在读端存储不同排序的集合。
综上所述,Delete命令是在写端更改集合,而Reoder命令只是用户或集合设置。因此,这里没有并发性。
根据你的意见和澄清。
- 当然,您可以并且可能应该一次只限制一个用户操作。如果删除和重新排序的时间相当短。这总是一个用户体验类型的问题。以订购系统为例。下订单后,用户几乎可以立即在UI中看到它,状态将类似于InProcess。最有可能的是,您不会让用户以任何方式更改顺序,这意味着您不会显示任何用户控件,如取消按钮(当然这只是一个示例)。因此,您可以在这里使用这种方法。
- 如果2个用户可以修改相同的物理集合,那么你别无选择——你正在使用共享数据,应该有一种同步。例如,如果您正在使用传奇,则可能有两个传奇:集合重新排序传奇和删除传奇-它们可以合作。删除进程首先启动——收集聚合被标记为正在进行的删除,然后在这个重新排序事件开始之后,它将尝试启动重新排序过程,但由于删除事件正在进行中,它应该等待DeletedEvent,然后继续该过程。如果重新排序操作首先开始,则相同-删除传奇应该等待某个事件,并在该事件到达后继续。
好,如果我们同意不触及文件系统本身,而是代表图片集合的聚合。最重要的并发问题可以用乐观并发方法来解决——在数据存储中,通常使用基于聚合id和聚合版本的唯一约束。
以下是命令处理程序中的典型步骤: 以下是命令处理程序遵循的常见步骤序列:- 验证命令本身的优点。
- 加载聚合。
- 验证当前聚合状态下的命令。 创建一个新事件,将该事件应用到内存中的聚合。
- 尝试保存聚合。如果在此步骤中存在并发性冲突,要么放弃,要么重试步骤2中的内容。
这是一个链接,帮助我很多前一段时间:http://www.cqrs.nu/