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

Dealing with queued command handler response. CQRS

考虑情况:

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. 最终用户如何获得 immediate/synchronous ui 响应,以反映对域所做的真实更改?我应该这样做吗?

  3. 通过消息总线处理传入命令是否仅适用于后台任务而不需要确认?

这在某种程度上取决于您的命令总线实现。一些系统允许命令处理程序将回复发送回原始发件人。

您的情况的标准解决方案是不确认实际的 checkout,而只是确认命令的 receipt 和现在正在处理结帐。对于结账,这通常完全没问题,因为无论如何订单都需要几个小时才能得到处理。

如果您确实需要立即显示一些结果,当在给定时间范围内没有预期结果时,您可以轮询另一个服务的完成状态 and/or 超时。

如果这对您来说太复杂,请不要使用异步命令总线,而是执行同步命令处理,在这种情况下,故障会立即传播到客户端。

本文摘自 «Busting some CQRS myths», Jimmy Bogard blog 您可能感兴趣:

Myth #4 – Commands are fire-and-forget

How many business processes in your line of work are truly fire and forget? You typically need at least a synchronous acknowledgement that the command was received and accepted. If you’re doing an async send of the command, how do you notify the user? Email? Are they OK with this?

Instead, with commands that need heavy lifting to fulfill the request, we really have two things going on:

  • Accepting the request
  • Fulfilling the request

Accepting the request should be synchronous. Fulfilling need not be. But for the model of an asynchronous fulfillment, we still will likely need ways of correlating requests etc., and this is where you often see workflows/processes/sagas come into play.

我总是尝试让我的命令同步。如果流程时间很长,我会使用流程管理器或 saga 之类的东西。

如果您确实想要发送请求并等待响应,您可以使用 IRequestClient 接口,并将 MessageRequestClient 的实例添加到您的容器中 - 并使用该依赖项代替直接使用 IBus。这将使您可以等待请求的响应,并且 return API.

上的内容

当然,您已经将控制器与服务的可用性相结合——这并不总是一件坏事——但需要注意一些事情。

使用请求客户端的示例代码可以在文档中找到,这是一个与您描述的完全相同的网络案例。

http://docs.masstransit-project.com/en/mt3/usage/request_response.html