代码之家  ›  专栏  ›  技术社区  ›  Roshan

如何使用CQRS和事件源处理依赖于应用程序中现有记录的命令

  •  3
  • Roshan  · 技术社区  · 8 年前

    我们将CQRS与EventSourcing结合使用。

    在我们的应用程序中,我们可以从ui添加资源(这是单个项目的商业术语),并相应地发送命令来添加资源。

    所以我们在应用程序中有x个先前添加的资源。 现在,我们有一种特殊类型的资源(我称之为SpecialResource)。 当我们添加这个SpecialResource时,id需要与应用程序中的所有现有资源链接。 链接意味着此SpecialResource应该具有现有资源的ID(GUID)列表(List)。

    在添加特殊资源之前,我们尝试在应用程序中获取所有资源ID的解决方案 资源(即在启动AddSpecialResource命令之前)。 将这些列表分配给特殊资源,然后发送AddSpecialResource命令。

    但我们不应该这样做,因为根据cqrs命令,不应该查询。 一、 e.命令不能依赖于查询,因为查询可能有过时的记录。

    我们如何在不查询应用程序中的现有记录的情况下实现此业务场景?

    4 回复  |  直到 8 年前
        1
  •  1
  •   VoiceOfUnreason    8 年前

    但我们不应该这样做,因为根据cqrs命令,不应该查询。一、 e.命令不能依赖于查询,因为查询可能有过时的记录。

    这不太正确。

    “命令”始终运行查询。如果您使用事件源,在大多数情况下,您的命令 queries--“如果允许此命令,将生成哪些事件?”

    这与您描述的情况之间的区别在于聚合边界,在事件源域中,聚合边界是事件流的一个奇特名称。允许聚合在处理命令时针对其自身的事件流(也就是说,其自身的状态)运行查询。是其他聚合(事件流)超出了界限。

    实际上,这意味着 如果 SpecialResource确实需要与其他资源ID在事务上保持一致,那么所有这些数据都需要是同一聚合的一部分,因此也是同一事件流的一部分。

    因此,如果到目前为止,您一直在使用单独的流对资源进行建模,现在您需要SpecialResource来完成您所描述的工作,那么您需要对您的域模型进行相当大的更改。

    好消息是:这可能不是你真正的要求。考虑您迄今为止所描述的内容-如果resourceId:99652是在SpecialResource之前一毫秒创建的,那么它应该包含在Special Resource的状态中,但如果它是在一毫秒之后创建的,则不应该包含在该状态中。所以 企业的成本是多少 如果在SpecialResource丢失前一毫秒创建的资源?

    因为,从先验来看,这听起来不应该太贵。

    更常见的是,真正的需求看起来更像是“SpecialResource需要包括在业务结束之前创建的所有资源id”,但实际上直到业务结束后5分钟才需要SpecialResort。换句话说,这里有一个SLA,您可以使用该SLA更好地通知您的命令。

    我们如何在不查询应用程序中的现有记录的情况下实现此业务场景?

    把它转过来;运行查询,将查询结果(资源id)复制到创建SpecialResource的命令中,然后分派该命令以传递给您的域模型。CreateSpecialResource命令包含正确的资源ID列表,因此聚合不需要担心如何发现这些信息。

        2
  •  0
  •   Roman Susi    8 年前

    很难判断数据库的功能,但添加“快照”最一致的方法是在数据库层,因为在纯CQRS中没有其他常见的地方。(有一些关于CQRS+ES快照的文章,如果这是您实际尝试用SpecialResource实现的话)。

    一种方法可能是在AddSpecialResource命令到达(数据库)时,使用某种存储过程来具体化ID列表。

    另一种方法是使用一些标记(时间戳)捕获“所有现有资源(截至目前)”,永远不要删除旧资源,并在查询中添加“SpecialResource”条件,这将使用SpecialResort数据。

    好的,还有一个选项(取决于您手头的情况)是始终在同一查询中使用ID列表,这为UI提供了服务。这样,“所有资源”的定义变为“用户(在某个时刻)看到的所有资源”。

        3
  •  0
  •   Eben Roux    8 年前

    我不认为任何一个计算机系统都会100%一致,因为生活不会也不可能这样工作。显然,我们都生活在过去,因为你的大脑需要时间来处理输入。

    重点是,您尽最大努力处理手头的信息,但确保您的系统能够平滑任何边缘。因此,如果您需要将一个或两个资源与您的 SpecialResource 那么你应该能够做到这一点。

    所以即使你 能够 将您的 特殊资源 对于数据存储中的所有现有条目,也就是说没有另一个尚未输入系统的资源也需要关联。

    和往常一样,这一切将取决于您的特定用例。这就是为什么流程管理器和他们的状态一起,使人们能够按摩该状态,直到流程完成。

    我希望我没有误解你的问题:)

        4
  •  0
  •   IlliakaillI    8 年前

    你可以做两件事来解决这个问题:

    • 区分写和读模型。你知道什么是阅读模式,对吧?因此,相比之下,数据的“写入模型”是数据结构和行为的组合,它足以强制执行所有不变量,并生成一致的事件作为每个执行命令的结果。

    • 不要把“事件存储是唯一的真相来源”这条规则太过字面化。考虑以下解释:ES是您的应用程序的所有真相的单一来源,然而,对于每个特定命令,您可以创建“编写模型”,它将提供足够的“真相”,以使该命令保持一致。