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

时间:2016-10-26 12:32:08

标签: synchronization cqrs rebus

我尝试使用CQRS / ES架构设置WebApp。 我已经使用Create和Edit命令/事件定义了一个模型实体。 命令由相关的Saga处理。 事件将保存到mongo事件存储中,这是立即一致的存储。 事件由写入最终一致的SQL存储的非规范化程序处理。

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

成功回调(并且因为发出命令没有问题),客户端刷新实体列表。如果非规范化程序仍然没有处理实体Created事件,并且写入最终一致的SQL存储,则该页面仍将显示空列表。 我想要的是一种方法,使发出Create命令的方法等待denormalizer。

我阅读了很多博客和内容,并且我认为这种同步违背了使用总线的想法......但是这样的用户操作需要同步:如何向用户呈现"插入成功!"然后仍然看到一个空列表??

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

2 个答案:

答案 0 :(得分:2)

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

Rebus本质上是异步的,听起来你的整个设置都围绕这个前提建立。

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

说了 - :)我知道如何使异步操作看起来是同步的:只需轮询读取存储直到你的更改可见!

您可以检测您的更改是否可见或多或少是通用的,从简单轮询到创建的用户弹出,到为您的命令提供各种类型的相关ID,然后以某种方式传输所有(重新)预测,然后由发起客户发现。

但请考虑这是一个黑客。请看看你是否可以以某种方式避免假装同步,或考虑其他技术是否更适合。

答案 1 :(得分:2)

前一阵子写了一篇关于这个主题的博客文章。我提供了4种可能的解决方

  1. 禁用和刷新 - 此处的想法是在指定的时间段过后禁用编辑字段。我个人不喜欢这种方法,因为它会产生糟糕的用户体验,但仍然可能无法工作,具体取决于完成阅读模型更新的时间。

  2. 使用确认屏幕 - 这是进程结束屏幕的理想选择。就像一个“谢谢你的订单”#39;或类似的。

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

  4. 轮询 - 正如已经建议的那样,您可以对读取模型使用轮询或订阅。我也使用了这种方法,但将它与选项3结合起来。它适用于像React这样的框架。

  5. 您可以在此处阅读完整帖子:4 Ways to Handle Eventual Consistency