Ринат Абдуллин написал хороший обзор саг / менеджеров процессов .
Обычный ответ: у саги есть копии событий, о которых она заботится, и использует информацию этих событий для вычисления командных сообщений для отправки.
List[Command] processManager(List[Event] events)
Нажав их через команду ReserveEmail и полученное событие?
Да, это обычный подход; мы получаем список [RegistrationStarted]
и используем его для вычисления результата [ReserveEmail]
. Позже мы получим [RegistrationStarted, EmailReserved]
, и мы можем использовать это для вычисления следующего набора команд (если есть).
Звучит скучно.
Данные должны как-то перемещаться между двумя возможностями. Таким образом, вы либо копируете данные из одного сообщения в другое, либо копируете идентификатор корреляции из одного сообщения в другое, а затем позволяете потребителю решить, как использовать идентификатор корреляции для извлечения копии данные.
Хранить эти данные в саге? Но они не используются для защиты инвариантов.
Обычно вы будете хранить события в сагах (чтобы отслеживать, что произошло). Это дает вам копию данных, предоставленных на мероприятии. У вас нет инварианта для защиты, потому что вы просто кэшируете копию решения, принятого где-то еще . Обычно у вас не будет менеджера процессов, выполняющего запросов для сбора дополнительных данных.
А как насчет возможной последовательности?
По своей природе саги всегда будут "в конце концов последовательными"; «Состояние» экземпляра саги - это просто кэшированные копии данных, контролируемых в другом месте. Данные, вероятно, устарели на наносекунды к тому времени, как их увидит сага, нет смысла притворяться, что данные «сейчас».
Если я правильно понимаю, я мог бы смоделировать свою сагу как агрегат регистрации, хранящий все события, чей корреляционный идентификатор является его собственным идентификатором?
Уди Дахан, пишет о CQRS :
Вот самое убедительное указание, которое я могу вам дать, чтобы знать, что вы правильно выполняете CQRS: ваши совокупные корни - саги.