我想知道外部系统(具体来说:Web服务)的请求应该放在基于CQRS的系统中。
例如,给定一个向外部航班服务发送预订请求的系统: 它应该在域对象中,在“bookFlight”的命令处理程序中吗?或者这应该是一个传奇,作为对域对象事件“flightBookingPlaced”的反应?
答案 0 :(得分:2)
我会做一些假设:
我会说它可以属于命令或一系列命令。
隐藏ACL或外观背后的外部服务,使其成为对命令的依赖。然后该命令将表示从“未预订”到“已预订”的转换。忽略命令“阻塞”的复杂性直到完成(有效),这将涵盖你需要的东西。
如果您想支持更细粒度的方法,那么一系列小命令方法感觉最适合:
not booked -> booking pending -> booked
启动活动并触发RequestBookingCommand
,将预订状态从“未预订”更改为“预订待处理”,并提交交易。然后,这可以触发下一个命令ExternalBookingCommand
,该命令可以在后台运行,而不需要最初的域对象。预订可以在外部系统上进行,如果成功,可以从“预订待定”到“预订”。如果失败,您可以重试或将预订还原为“预订失败”。
这至少可以让你开始进行验证而不是试图双书等。
我不能特别谈到传奇,但我想你可以代表“预订命令”的协议作为一个小故事;将您从一个域状态(未预订)映射到最终状态(已预订),并在您之间使用尽可能多的停靠点。
在任何一种方法中,重要的是保护域状态并确保任何事务都是不可或缺的。更详细地了解状态和事件也可能有所帮助,因为您可以使用更好的语言(DDD的原则之一)来描述正在发生的事情,例如RequestBookingCommand
让您处于BookingRequested
状态,然后进入PerformExternalBooking
命令以BookingRequested
状态开头,让您处于Booked
或BookingFailed
状态。然后,您还可以引入SuccessfullyBooked
或BookingRequestedOnFoo
等域事件。
我对这些情况的处理方法通常是尽量不要过度思考它,然后首先建立一个与口头描述方式相匹配的模型。框架和基础架构可以帮助您解决技术问题(例如事务或并发)。
答案 1 :(得分:0)
如果这不是一个内部的微服务 - 真的快速和稳定,我会在Saga / Process Manager / Gateway - 一个拥有自己的状态机的异步actor这样做。 使用外部服务,您可能希望进行错误处理,重试,超时 - 所有异步,因此您的聚合不会被阻止。