CQRS按特定顺序运行处理程序

时间:2013-04-18 15:24:54

标签: c# events cqrs handlers

我有2个处理程序的正在运行的订单删除和重新排序图片,并希望得到一些建议,以获得最佳解决方案。

在UI上删除一些图片,用户点击删除的按钮。启动整个流,删除命令直到实际删除物理文件的事件处理程序。

然后用户立即对剩余的图片进行排序。从重新排序命令到文件系统的重新排序事件处理程序的新流程再次触发。

已经存在并发问题。如果没有完成删除,则无法正确应用重新排序。目前,这个问题是通过某种锁定来处理的。创建临时文件,然后在删除流程结束时删除。当该文件存在时,另一个线程(根据用户操作重新排序或删除)等待。

这不是一个理想的解决方案,我想改变它。 潜在的解决方案也必须非常快(当然不是快速的解决方案)因为UI在订购结束时通过JSON调用进行更新。

在稍后的实现中,我们正在考虑使用事件队列,但目前我们已经陷入困境。

任何想法都将不胜感激! 谢谢,mosu'!

编辑: 通过在客户端使用Javascript数据管理器解决了我们遇到的其他最终一致性问题。基本上是乐观主义者和欺骗用户! :) 我开始相信这也是去这里的方式。但那我怎么知道文件系统中的数据何时发生变化?

2 个答案:

答案 0 :(得分:0)

这是一个想法。 究竟是什么重新排序?图片?以日期为基础。 为什么有命令呢?每个人或这个特定用户都会看到这个命令的结果?

我只能猜测,但看起来你在这里有一个演示问题。不需要在写入端以某种顺序存储图片,它只是名称列表和文件存储的链接。您应该做的是在用户设置或集合设置中的某处存储一个小字段:日期升序或名称降序。因此,命令重新排序应仅更改此小字段。然后,当您加载图库时,应首先读取此字段,并根据此字段加载一个或另一个视图。由于现在商店很便宜,你可以在读取端存储不同排序的集合,用于你需要的每种类型的参数。

总而言之,Delete命令正在改变写入侧的集合,但Reoder命令只是用户或集合设置。因此,这里没有并发性。

<强>更新

根据您的意见和澄清。

  1. 当然,您可以并且可能应该仅限制用户操作。如果删除和重新排序的时间相当短。这始终是您被要求实现的用户体验类型的问题。以订购系统的常见示例为例。下订单后,用户几乎可以立即在UI中看到它,状态将类似于 InProcess 。很可能你不会让用户以任何方式更改订单,这意味着你不会显示任何用户控件,如取消按钮(当然这只是一个例子)。因此,您可以在此处使用此方法。
  2. 如果2个用户可以修改相同的物理集合,那么您在这里别无选择 - 您正在使用共享数据,应该有一种同步。例如,如果你正在使用传奇,可能会有一些传奇:收集重新排序传奇和删除传奇 - 他们可以合作。删除过程首先启动 - 集合聚合被标记为正在删除,然后在此重新排序saga开始之后,它将尝试启动重新排序过程,但由于删除saga正在进行中,它应该等待DeletedEvent并继续之后的过程。如果重新排序操作首先开始 - 删除传奇应该等到某个事件并在该事件到达后继续。
  3. <强>更新

    好的,如果我们同意不接触文件系统本身,而是代表图片集合的聚合。最重要的并发问题可以通过乐观并发方法解决 - 在数据存储中,通常使用基于聚合ID和聚合版本的唯一约束。

    以下是命令处理程序中的典型步骤:

    这是命令处理程序遵循的常见步骤序列:

    1. 根据自身优点验证命令。
    2. 加载聚合。
    3. 验证聚合当前状态的命令。
    4. 创建一个新事件,将事件应用于内存中的聚合。
    5. 尝试保留聚合。如果在此步骤中存在并发冲突,请放弃或重试步骤2中的内容。
    6. 以下是很久以前给我很多帮助的链接:http://www.cqrs.nu/

答案 1 :(得分:0)

最受欢迎的建议非常受欢迎,通常适用。

有时很难解释实现的所有细节,但有一个细节应该提到: 我们存储图片的方式意味着当重新排序时所有图片路径(以及所有链接)都会发生变化。

一位同事非常清楚地删除这一部分。这意味着即使订单将改变图片的路径将保持不变。在UI端,将在显示顺序中的图片索引与其路径之间进行映射,这意味着除了删除时,不再需要更改文件系统。

我们希望尽可能让用户感到宽容,这对我们来说是最好的解决方案。 我认为,一般来说,当出现并发问题时,它也是一种很好的方法。可以删除并发吗?