【问题标题】:CQRS run handlers in specific orderCQRS 按特定顺序运行处理程序
【发布时间】:2013-04-27 19:54:48
【问题描述】:

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

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

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

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

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

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

任何想法将不胜感激! 谢谢你,摩苏!

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

【问题讨论】:

  • 您正在使用 CQRS 和一个以事件为中心的架构,并为图片库提供最终一致性?我相信你有你的理由,我真的很好奇它们是什么。 CQRS 并不适合一切。仍然应该使用 KISS。
  • 并非如此。图片库只是车辆管理网站的一部分。到目前为止,我们还没有在这样的并发上下文中使用某些资源的情况。此外,到目前为止,CQRS 对我们来说效果很好。我们仍在学习,也希望向其他用户学习!

标签: c# events cqrs handlers


【解决方案1】:

Max 建议非常受欢迎,通常它们适用。

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

一位同事认为删除这部分是个好主意。这意味着即使顺序会改变图片的路径也将保持不变。在 UI 端,显示顺序中的图片索引与其路径之间会有一个映射,这意味着除了删除时,无需再更改文件系统。

我们希望对用户尽可能宽容,这对我们来说是最好的解决方案。 我认为,总的来说,当出现并发问题时,这也是一种好方法。可以去掉并发吗?

【讨论】:

    【解决方案2】:

    这是一个想法。 你到底在重新订购什么?图片?例如,基于日期。 为什么有这个命令?这个命令的结果会被所有人看到还是只被这个特定的用户看到?

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

    总而言之,Delete 命令是在写入端更改集合,而 Reoder 命令只是用户或集合设置。因此,这里没有并发。

    更新

    根据您的 cmets 和说明。

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

    更新

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

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

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

    1. 根据自身的优点验证命令。
    2. 加载聚合。
    3. 根据聚合的当前状态验证命令。
    4. 创建一个新事件,将该事件应用于内存中的聚合。
    5. 尝试保持聚合。如果在此步骤中存在并发冲突,请放弃,或从第 2 步重试。

    这是前段时间对我帮助很大的链接:http://www.cqrs.nu/

    【讨论】:

    • 我认为我以一种有点误导的方式提出了我的问题。以下是导致问题的步骤: 用户删除 3 张图片,发送删除命令并在某些时候删除物理图片(在我们的解决方案中,删除意味着重新排序)。一秒钟后,用户使用图片。重新排序命令已发送,但如果删除未在物理上完成,则会发生令人讨厌的事情。我喜欢不重新排序而只更改和索引的想法,但这是一个(很大并且被其他单体使用的)遗留系统。我不确定这是否适合我们。谢谢你的回答!
    • 好的,我了解 Delete 命令的作用 - 它会删除文件并最终更改 Collection 聚合。但是你说的重新排序是什么意思?只是集合聚合中的项目顺序还是文件系统上的一些物理顺序?
    • 图片根据文章id、图片大小和一些数学算法存储在文件系统中,因此只需知道文章id就可以创建图片的路径。这意味着每篇文章都有一个文件夹结构。当用户重新排序(对图片进行排序)时,路径会发生变化,因此必须四处移动图片。排序在聚合中也发生了变化。谢谢!
    猜你喜欢
    • 2019-03-02
    • 1970-01-01
    • 2023-03-15
    • 2012-07-12
    • 1970-01-01
    • 2010-09-05
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    相关资源
    最近更新 更多