gpt4 book ai didi

domain-driven-design - 解决框架 : How to properly derive an aggregate's state from the state of other aggregates?

转载 作者:行者123 更新时间:2023-12-04 10:37:57 24 4
gpt4 key购买 nike

我正在用 reSolve 做我的第一个项目,但在 DDD、ES 和 CQRS 方面的经验有限。所以,也许有一个非常简单的解决方案,但我还没有找到。

我的问题:在我的项目中,一个聚合的状态(订单状态)实际上源自其他聚合的状态(属于该订单的每个工作步骤的状态;可以有两个或多个工作步骤同时进行时间,每个都有自己的状态,例如错误或完成)。

经过一些研究,我的想法是在工作步骤聚合的每个命令处理程序中调用一个额外的命令(类似于“updateOrderStatus”),例如:

    pauseWorkStep: (state, { payload: { orderId } }) => {
async ({ resolve }) => await resolve.executeCommand({
aggregateName: 'Order',
aggregateId: orderId,
type: 'updateOrderStatus',
payload: {}
})
return {
type: WORKSTEP_PAUSED,
payload: {}
}
}

此“updateOrderStatus”命令将位于订单聚合中。相应的投影函数必须在其读取模型中查询工作步骤的当前状态 - 或多或少是这样的(这只是为了展示主要思想):
    [ORDER_STATUS_UPDATED]: (state, { timestamp }) => ({
...state,
updatedAt: timestamp,
status: () => {
const workStepStatus = async ({ resolve }) => await resolve.executeQuery({
modelName: 'WorkSteps',
resolverName: 'workStepByOrderId',
resolverArgs: { orderId }
})
switch (workStepStatus) {
case "paused":
// define status
break;
case "finished":
// define another status

...
}
}
})

基于此,可以确定订单的状态。
问题是,这可能会导致不一致,因为读取模型可能已经过时。

我如何在 reSolve 框架中解决这个问题?或者,是否有另一种方法可以做到这一点而不违反 DDD、CQRS 和 ES 的原则?

谢谢你帮我解决。

最佳答案

看来您的聚合定义太细化了。聚合根不是一个实体,它可以是具有单个根的实体的集合。

聚合定义了事务和一致性边界。
因此,如果您看到该命令应将多个聚合作为事务影响,这很好地表明它们实际上是单个聚合。

在您的情况下,我猜您可以将 Order 设为聚合,因此 pauseWorkStep 命令将发送到 Order,而不是 WorkStep。

这样做的深层原因是一致性:保证聚合处于一致状态。在您的方法中,没有单个事务,如果一个命令成功而另一个命令失败怎么办?如果其他用户在您的用户之间发送另一个命令怎么办?您无法在命令处理程序中控制它。

如果您确实需要编排多个聚合,则需要创建一个 saga/processManager - 这是一个长时间运行的业务事务。

另请参阅最近对类似主题的讨论:Should a single command address multiple aggregates?

关于domain-driven-design - 解决框架 : How to properly derive an aggregate's state from the state of other aggregates?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60075193/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com