gpt4 book ai didi

design-patterns - CQRS 和命令去抖动

转载 作者:行者123 更新时间:2023-12-03 10:34:04 25 4
gpt4 key购买 nike

我有以下任务:

  • 我们当前的架构是带有 CQRS 和 MVVM 的 Web SPA。我们有
    命令、查询和 SingnalR 作为消息总线。
  • 用户可以同时从多个 Web 浏览器中选择、移动、调整同一工作区中的 div。
  • 每个 div 都绑定(bind)到适当的 ViewModel。每个 ViewModel 都有自己的查询来刷新。每个 ViewModel 订阅业务事件并在其之后刷新整个状态。

  • 让图像显示用户正在执行以下步骤:
  • 选择 div(已发送 SelectWidgetCommand)
  • 将 div 移动到 x=10。 (已发送更改位置命令)
  • 将 div 移动到 x=100。 (已发送更改位置命令)

  • 问题是命令是即发即弃的,用户可能会在第 3 步期间收到事件 WidgetSelectedEvent,但可能尚未处理 ChangePositionCommand。所以用户将收到旧的 x 位置,而 div 将移动到旧位置。

    处理此类问题的最佳做法是什么?

    我们现在所做的是将 DivViewModel 拆分为两个 div:SelectionViewModel、PositionViewModel。每个 ViewModel 都有自己的要刷新的查询和要处理的不同事件。我们还考虑使用去抖动和滚动缓冲区来处理命令。

    最佳答案

    您可能想查看 Greg Young 在 occasionally connected systems 上的演讲.

    The problem is that the commands are fire-and-forget


    您如何理解“即发即弃”?如果模型不允许拒绝发送给它的命令,那么您发送的消息是事件,而不是命令。
    CQRS 中写入模型的通常实现是将命令线性化(一次处理一个)。命令应确保满足其先决条件。 Compare-And-Set ,而不是 Set .
    在最简单的形式中,命令指定它们将要修改的聚合的初始版本,与 HTTP 中的条件请求指定 preconditions on the resource 的方式非常相似。 .在竞争条件的情况下,多个命令试图更改模型的同一部分,一个命令将获胜,而失败者将被轻易拒绝。
    更好的(但更多的工作要实现)是为失败的命令实现一种第二次机会——在模型中建立足够的理解,它可以确定两个命令引起的变化是否冲突。如果他们不这样做,那么您只需将它们链接在一起。
    另一种方法是允许两个写入发生,并接受存在冲突。想想源代码控制系统的工作方式:我提交了历史 1-2-X,你提交了历史 1-2-Y,现在有两种选择,直到有人通过合并来协调它们。
    这种方法与 Udi Dahan 在他的文章 Race Conditions Don't Exist 中的中心点大致一致。 .

    A microsecond difference in timing shouldn’t make a difference to core business behaviors.


    如果您的 View 是根据事件列表构建的(正如您在此处描述的那样),那么可以从 CRDT 开始。的一个列表。 Mark Klepmann 描述了一个 JSON data type (hacker new commentary) .这不会让你“没有冲突”,但它确实让你知道看到相同单个事件的两个用户必然会以相同的顺序出现(如果有问题,那么每个人都会看到相同的问题)。
    但 Greg 的方法可能更易于实现——作者使用共享模型的本地副本并与之交互,但该共享模型是一个近似值,无法通过记录簿核对的命令返回给作者手动缓解。

    关于design-patterns - CQRS 和命令去抖动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40994861/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com