Domain driven design 解析框架:如何正确导出聚合';s状态与其他聚合状态的区别?

Domain driven design 解析框架:如何正确导出聚合';s状态与其他聚合状态的区别?,domain-driven-design,cqrs,event-sourcing,resolvejs,Domain Driven Design,Cqrs,Event Sourcing,Resolvejs,我正在做我的第一个项目与决心和有限的经验,在DDD,ES和CQR。所以,也许有一个非常简单的解决办法,我只是还没有找到 我的问题:在我的项目中,一个聚合的状态(订单的状态)实际上来自于其他聚合的状态(属于此订单的每个工作步骤的状态;可以有两个或多个工作步骤同时进行,每个步骤都有自己的状态,例如错误或完成) 经过一些研究,我的想法是在工作步骤聚合的每个命令处理程序中调用一个额外的命令(称为“updateOrderStatus”),例如: pauseWorkStep: (state, { p

我正在做我的第一个项目与决心和有限的经验,在DDD,ES和CQR。所以,也许有一个非常简单的解决办法,我只是还没有找到

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

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

    pauseWorkStep: (state, { payload: { orderId } }) => {
        async ({ resolve }) => await resolve.executeCommand({
            aggregateName: 'Order',
            aggregateId: orderId,
            type: 'updateOrderStatus',
            payload: {}
        })
        return {
            type: WORKSTEP_PAUSED,
            payload: {}
        }
    }
此“updateOrderStatus”命令将位于订单聚合中。相应的投影函数必须在其读取模型中查询工作步骤的当前状态——或多或少是这样(这只是为了说明主要思想):

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

如何在reSolve框架中解决此问题?或者,是否有其他方法做到这一点,并且不违反DDD、CQRS和ES的原则


谢谢您的帮助。

您的聚合定义似乎过于精细。聚合根不是实体,它可以是具有单个根的实体集合

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

在您的情况下,我想您可以将Order设置为聚合,因此pauseWorkStep命令将发送到Order,而不是工作步骤

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

如果确实需要协调多个聚合,则需要创建一个saga/processManager,这是一个长期运行的业务事务


另请参见最近关于类似主题的讨论:

首先,感谢您的回答。我有多个后续问题,但我将从您首先提到的内容开始:在reSolve中,是否有某种方式来定义什么是实体,什么是聚合根(例如在.NET framework中)?
    [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

                ...
            }
        }
    })