CQRS - 我应该在哪里向外部系统发出请求?

时间:2017-11-22 11:39:51

标签: cqrs

我想知道外部系统(具体来说:Web服务)的请求应该放在基于CQRS的系统中。

例如,给定一个向外部航班服务发送预订请求的系统: 它应该在域对象中,在“bookFlight”的命令处理程序中吗?或者这应该是一个传奇,作为对域对象事件“flightBookingPlaced”的反应?

2 个答案:

答案 0 :(得分:2)

我会做一些假设:

  • 外部请求是“交易”的一部分。
  • 外部请求是命令行为的核心。
  • 外部系统响应是同步的,无论是响应还是失败,都没有回调或轮询。

我会说它可以属于命令或一系列命令。

隐藏ACL或外观背后的外部服务,使其成为对命令的依赖。然后该命令将表示从“未预订”到“已预订”的转换。忽略命令“阻塞”的复杂性直到完成(有效),这将涵盖你需要的东西。

如果您想支持更细粒度的方法,那么一系列小命令方法感觉最适合:

not booked -> booking pending -> booked

启动活动并触发RequestBookingCommand,将预订状态从“未预订”更改为“预订待处理”,并提交交易。然后,这可以触发下一个命令ExternalBookingCommand,该命令可以在后台运行,而不需要最初的域对象。预订可以在外部系统上进行,如果成功,可以从“预订待定”到“预订”。如果失败,您可以重试或将预订还原为“预订失败”。

这至少可以让你开始进行验证而不是试图双书等。

我不能特别谈到传奇,但我想你可以代表“预订命令”的协议作为一个小故事;将您从一个域状态(未预订)映射到最终状态(已预订),并在您之间使用尽可能多的停靠点。

在任何一种方法中,重要的是保护域状态并确保任何事务都是不可或缺的。更详细地了解状态和事件也可能有所帮助,因为您可以使用更好的语言(DDD的原则之一)来描述正在发生的事情,例如RequestBookingCommand让您处于BookingRequested状态,然后进入PerformExternalBooking命令以BookingRequested状态开头,让您处于BookedBookingFailed状态。然后,您还可以引入SuccessfullyBookedBookingRequestedOnFoo等域事件。

我对这些情况的处理方法通常是尽量不要过度思考它,然后首先建立一个与口头描述方式相匹配的模型。框架和基础架构可以帮助您解决技术问题(例如事务或并发)。

答案 1 :(得分:0)

如果这不是一个内部的微服务 - 真的快速和稳定,我会在Saga / Process Manager / Gateway - 一个拥有自己的状态机的异步actor这样做。 使用外部服务,您可能希望进行错误处理,重试,超时 - 所有异步,因此您的聚合不会被阻止。