Rebus - 发送命令并等待处理程序

Rebus - send command and wait for handlers

我正在尝试使用 CQRS/ES 架构设置 WebApp。 我已经定义了一个模型实体,创建和编辑 commands/events。 命令由相关的 Saga 处理。 事件保存到 mongo 事件存储,这是即时一致的存储。 事件由写入最终一致 SQL 存储的反规范化程序处理。

现在我正面临来自 WebApp 的应同步 CRUD 操作的问题:用户打开一个页面,其中包含这些实体的列表,这些实体是从最终一致的 SQL 存储中读取的。最初它是空的。 然后,用户编译一个表单来添加一个新的实体。客户端执行 ajax 调用向总线发出创建命令的方法,然后 returns 无效。

回调成功后(确实如此,因为发出命令没有问题),客户端会刷新实体列表。如果非规范化程序仍未处理实体 Created 事件,并写入最终一致的 SQL 存储,页面仍将呈现一个空列表。 我想要的是一种使发出 Create 命令的方法等待反规范化器的方法。

我读了很多博客和东西,我明白这种同步与使用总线的想法背道而驰......但是这样的用户操作需要同步:如何向用户呈现"insert successful!" 然后仍然看到一个空列表??

我希望得到答案,因为这个用例对我来说似乎很基础...

我认为这里的问题是,如果您需要同步命令,您可能选择了错误的技术来处理您的命令...

Rebus 本质上是异步的,听起来您的整个设置也是围绕这个前提构建的。

我可以想出几种使异步看起来同步的方法,但首先我想指出,在我推荐之前,你不应该在超过几个(很少)的地方有这个要求你在没有异步命令处理的情况下实现你的 CQRS(例如,通过使用像 Cirqus 这样的东西,它可以等待一个或多个特定的视图赶上,或者通过手动滚动它)。

话虽如此 - :) 我有一个关于如何使异步操作看起来同步的想法:只需轮询读取存储,直到您的更改可见!

您可以或多或少地检测您的更改是否可见,范围从简单轮询直到创建的用户弹出,到为您的命令提供各种相关 ID,然后将其传输到所有以某种方式处理所有(重新)投影,然后可以由发起客户端发现。

但请将此视为 hack。请看看您是否可以以某种方式避免假装同步的需要,或者考虑是否有其他技术更适合。

不久前,我就这个主题写了一篇博客 post。我提供了 4 种可能的解决方案。

  1. 禁用并刷新 - 这里的想法是在指定的时间段过去之前在提交后禁用编辑字段。我个人不喜欢这种方法,因为它会造成糟糕的用户体验,并且仍然可能无法正常工作,具体取决于完成读取模型更新的时间。

  2. 使用确认屏幕 - 这是进程结束屏幕的理想选择。像 'thank you for your order' 或类似的。

  3. Fake It - 这是一个不错的选择。它基于以下事实:未能收到异常或验证错误表示成功。因此,您可以假定读取模型的新状态。我在生产中使用了这种方法并且工作得很好。您需要注意版本号。它还提供了出色的用户体验。如果由于某种原因操作失败,您可以稍后通知用户。此方法还假设您在域内进行了全面的验证和检查。它还有助于使读取模型更新尽可能简单。

  4. 轮询 - 如前所述,您可以对读取模型使用轮询或订阅。我也使用过这种方法,但将其与选项 3 结合使用。它适用于像 React 这样的框架。

您可以在此处阅读完整的 post:4 Ways to Handle Eventual Consistency