ReSolve Framework: Как правильно вывести состояние агрегата из состояния других агрегатов? - PullRequest
1 голос
/ 05 февраля 2020

Я делаю свой первый проект с 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?

Спасибо за помощь.

1 Ответ

1 голос
/ 06 февраля 2020

Кажется, ваше совокупное определение слишком гранулировано. Агрегат root не является сущностью, это может быть набор сущностей с одним root.

Агрегат определяет границы транзакции и согласованности. Так что, если вы видите, что команда должна влиять на несколько агрегатов как транзакцию, это хороший признак того, что на самом деле это один агрегат.

В вашем случае, я думаю, вы можете сделать Order агрегатом, поэтому команда pauseWorkStep отправляется к Ордену, а не к Рабочему шагу.

Очень серьезная причина этого - последовательность: агрегат гарантированно находится в согласованном состоянии. В вашем подходе нет единой транзакции, что если одна команда будет успешной, а другая - неудачной? Что если какой-то другой пользователь отправит другую команду между вами? Вы не можете контролировать это в обработчике команд.

Если вам действительно нужно организовать несколько агрегатов, вам нужно создать saga / processManager - длительную бизнес-транзакцию.

См. Также недавнее обсуждение подобных топи c: Должна ли одна команда адресовать несколько агрегатов?

...