处理排队的命令处理程序响应。CQRS

6

考虑以下情况:

public class OrderController {
    IBus bus;

    public OrderController(IBus bus) {
        this.bus = bus;
    }

    public ActionResult Checkout(String orderId) {
        var command = new CheckoutOrderCommand(orderId);
        bus.Send(command);

        return Redirect("on-success-url");
    }
}

相应的命令处理程序(在另一个程序集中定义)正在等待处理传入的消息。

但是,我们已经通过发送return Redirect("on-success-url"); 来表示一切正常。

  1. 如果处理程序无法将更改保存到领域中怎么办?

    嗯,可以在命令处理程序侧使用队列来发布响应,以订阅Web应用程序到队列。

  2. 最终用户如何获得反映对领域所做实际更改的即时/同步UI响应?我应该这样做吗?

  3. 使用消息总线处理传入命令只适用于没有确认的后台任务吗?

3个回答

8
这段文字摘自Jimmy Bogard的博客文章《打破一些CQRS神话》,可能对你有兴趣:

神话#4-命令是发送后就忘记

在您的工作流程中,有多少业务流程确实是发送后就不再关心呢?您通常至少需要同步确认已接收并接受了该命令。如果您正在异步发送命令,如何通知用户?通过电子邮件吗?他们是否同意?

相反,对于需要大量努力才能满足请求的命令,我们真正做了两件事:

  • 接受请求
  • 满足请求

接受请求应该是同步的。满足请求则不需要。但是对于异步履行模式,我们仍然可能需要协调请求等方式,这就是您经常看到的工作流程/进程/ saga的地方。

我总是尝试使我的命令同步。如果存在长时间的处理时间,则使用类似于过程管理器或saga之类的东西。


4
如果您确实想发送请求并等待响应,可以使用接口,并向容器添加的实例 - 并使用该依赖项而不是直接使用。这将使您能够等待来自请求的响应,并在API上返回某些内容。
当然,您已经将控制器与服务的可用性耦合在一起 - 这并不总是件坏事 - 但需要注意。
使用请求客户端的示例代码可以在文档中找到,这是一个完全符合您描述的Web案例。 http://docs.masstransit-project.com/en/mt3/usage/request_response.html

2
这在一定程度上取决于您的命令总线实现。有些系统允许命令处理程序向原始发送方发送回复。
在您的情况下,标准解决方案是不确认实际的“结帐”,而只是确认命令的接收,并且现在正在处理结帐。对于结帐来说,这通常完全没问题,因为订单需要几个小时才能被处理。
如果您真的需要显示一些即时结果,可以轮询另一个服务以获取完成状态和/或在给定时间范围内没有预期结果时超时。
如果这对您来说太复杂了,请不要使用异步命令总线,而是使用同步命令处理,其中失败会立即传播到客户端。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接