我挖成CQRS和我正在寻找如何解决客户在最终一致的系统读取的文章。 考虑例如网上商店,用户可以添加项目到自己的购物车。 你怎么能保证客户端显示购物车中的物品,如果命令“AddItemToCart”的实际处理完成异步? 我明白了调度命令,异步和更新基于域事件中读取模型异步的原则,但我看不出这是从客户的角度来处理。
Answer 1:
这样做有它的几个不同的方法;
在等待,直到用户一致
只是轮询服务器,直到你得到更新的读取模式。 这是类似于奔显示。
确保通过2PC一致性
你有一个支持DTC队列; 和你的命令首先被放在那里。 然后,他们; 执行,发送事件,读模型更新; 所有单个事务中。 您还没有实际上已经获得使用这种方法虽然事情,所以不要做这种方式。
傻瓜客户端
放在本地存储的读取模式在客户端和更新他们的时候发送相应的事件 - 但你无论如何希望这个事件,所以你已经更新了购物车的JavaScript的视图。
Answer 2:
我建议你看看微软模式与实践小组对CQRS指导 。 尽管这仍然工作在进步,他们给一个解决问题你提的问题。
他们对需要反馈的命令的方法是异步提交命令,重定向到另一个控制器动作,然后轮询预期的变化或超时读取模式发生。 这是使用它的工作原理与浏览器更好的前进和后退导航按钮,并给出了基础设施的时候MVC控制器开始投票之前处理命令后重定向消息获取模式。
示例代码从这个RegistrationController使用ASP.NET MVC 4个异步控制器。
[HttpGet]
[OutputCache(Duration = 0, NoStore = true)]
public Task<ActionResult> SpecifyRegistrantAndPaymentDetails(Guid orderId, int orderVersion)
{
return this.WaitUntilOrderIsPriced(orderId, orderVersion)
.ContinueWith<ActionResult>(
...
);
}
...
private Task<PricedOrder> WaitUntilOrderIsPriced(Guid orderId, int lastOrderVersion)
{
return
TimerTaskFactory.StartNew<PricedOrder>(
() => this.orderDao.FindPricedOrder(orderId),
order => order != null && order.OrderVersion > lastOrderVersion,
PricedOrderPollPeriodInMilliseconds,
DateTime.Now.AddSeconds(PricedOrderWaitTimeoutInSeconds));
}
我可能会使用AJAX投票,而不必在服务器上被拦截的Web请求。
Answer 3:
后重定向-GET
你希望保存命令的执行时间获取被调用之前。 如果命令需要10秒什么来完成在后端,但得到的是所谓的1秒?
本地存储
在客户端上存储命令的结果,而命令熄灭来执行,你假定命令将通过没有错误。 如果后端运行到一个错误,同时处理命令? 然后,你有什么地方是不相符的。
轮询
轮询似乎是,实际上与最终一致性线的选项; 你不作假或假设。 您的投票机制可以是异步您的网页的一部分,如购物车页面组件投票,直到它得到的更新而无需刷新页面。
回调
你可以引进像网络挂接拨打电话回客户端,如果客户端能够接收这样的。 通过一旦命令由后台接受提供相关ID,一旦命令完成处理,后端可以通知的命令的状态前端与相关ID一起在命令是否经历了成功与否。 没有必要对任何投票的这种方法。