11

我对使用域事件构建读取模型的系统中的流程有点困惑。特别是,我们如何处理用户期望数据(及其视图)在他们完成命令时发生变化的事实,但由于我们的系统架构(发布事件的非阻塞调用),实际数据库可能不会在页面是否重新加载?

我希望使用事件和服务总线将我们其中一个系统的设计与 CQRS 更加内联。

假设我的流程是这样的:

  1. 用户单击视图中的按钮以执行从其帐户中删除付款方式的任务。

  2. 控制器调用 PaymentMethodRemovalService,将 accountId 和 paymentMethodId 传递给它。

  3. 控制器使用 AccountRepository 检索 Account 并调用 account.RemovePaymentMethod(id)

  4. 帐户验证可以发生操​​作并发布事件 PaymentMethodRemovedMessage(accountId, paymentMethodId)

  5. 因为事件发布是异步的,我们现在必须从服务返回并从控制器返回视图——但我们的实际数据还没有更新

  6. 处理程序 IHandle< PaymentMethodRemovedMessage > 听到事件并从数据库中删除实际行

那么,男人该怎么办?

我可以简单地说,删除显示付款方式的 div。这可能适用于 AJAX 场景,但如果我使用 Post-Redirect-Get 来支持非 JavaScript 客户端怎么办。然后我将触发我的 Get 并从 Query 端读取数据,可能在更新之前。

我是否只显示一条通知,说明他们删除付款方式的请求已提交?(这似乎并不友好,对于提交订单有意义,但对于更改地址则不然)。

有没有办法协调将更改实现为分离的异步事件并显示反映其当前更改的用户数据?

编辑:我的问题与CQRS、DDD 同步报告数据库非常相似, 我不得不说,那里给出的答案以及这里也提到的,有点味道 - 争吵 UI 以显示带外的更新可以这么说,读取数据库。我希望有一些更清洁的东西。

4

2 回答 2

8

如果您被锁定在请求/响应模型中,您可以采用关联请求/响应模式。有关详细信息,请查看 NSB 下载中的异步页面示例。这演示了 ASP.NET 设置中的请求/响应。如果您更喜欢的话,那里有一些 ASP.NET MVC 示例。

当您引入异步处理时,您接受数据将是陈旧的。有人可能会争辩说,在您查询数据库的那一刻,数据已经很旧(网络延迟、渲染时间等)。既然数据已经老了,那我们一定要问老了才够好?

要考虑的另一件事是您的处理有点乱。第 3 步应该在将命令发送到服务器之前验证命令,然后第 3 步、第 4 步将在第 6 步之后进行。仅当命令有效时才应更新数据库,并且仅当数据库成功更新时才应发布事件。

于 2010-10-06T23:36:58.350 回答
0

这个问题被称为“最终一致性”。有明确的方法来处理它。首先要说明的是,无论是否使用异步事件,每个系统都具有最终一致性。只是您选择使其明确,而大多数其他系统只是让用户等待更新完成。只要明确选择,这两种方法都是有效的。

不久前,我写了一篇关于这个主题的博客文章,您可能会觉得有帮助。你可以在这里找到它:在 UI 上处理最终一致性的 4 种方法

这是一个简短的版本:

选项 1 - 使用确认屏幕。如果您在手机上使用银行应用程序,您可能已经看到了这一点。转账一些钱,在流程结束时,您会被带到确认屏幕,然后再被带回您的账户。这使系统有时间恢复最新状态。

选项 2 - 伪造它。如果用户尝试的操作很可能成功,那么伪造它可能是一种合法的方法。这通常在购买需求量很大的门票时使用。您的交易可能会通过,但后来公司发现您的票在几毫秒前已经售出。对公司的好处是他们有销售而不是冒失去两个客户的风险。只要仔细构建系统,这种情况应该很少发生,因此总体上不是问题。

您还可以使用相关 ID 来订阅操作的成功或失败。

无论如何,希望能提供一些思考。

于 2017-06-22T13:57:48.140 回答