Streams
Некоторые авторы предлагают классифицировать события в «потоках», а многие авторы идентифицируют «поток» с «совокупным идентификатором».
Скажем событие car.repainted
, под которым мы имеем в виду, что мы перекрасили автомобиль с идентификатором 12345
в {color:red}
.
В этом примере идентификатор потока, вероятно, будет выглядеть примерно так: car.12345
или если у вас есть универсальные уникальные идентификаторы, то просто 12345
.
Некоторые авторы фактически предлагают сохранить поток событий в таблице со структурой, более или менее похожей на следующую (если вы используете реляционную):
| writeIndex | event | cachedEventId | cachedTimeStamp | cachedType | cachedStreamId |
| 1 | JSON | abcd | xxxx | car.repainted | 12345 |
- Столбец
event
содержит «исходный» объект значения события, наиболее вероятно сериализованный в JSON, если это реляционная БД.
-
writeIndex
только для администрирования БД и не имеет ничего общего с самим доменом. Вы можете «сбросить» ваши события в другую БД и переписать writeIndex без побочных эффектов.
- Поля
cached*
предназначены для простого поиска и фильтрации событий, и все они могут быть рассчитаны на основе самого события.
- Особо следует упомянуть
cachedStreamId
, который будет использоваться - по мнению некоторых авторов - для сопоставления с «агрегированным идентификатором, которому принадлежит событие». В данном случае «автомобиль идентифицируется как 12345
».
Если вы не используете реляционную систему, вы, вероятно, сохранили бы свое событие «как документ» в хранилище данных / хранилище событий / хранилище документов / или «позвоните как хотите» ( mongo, redis ,asticsearch ...) и затем вы создаете группы, группы, выборки или фильтры для извлечения некоторых событий по критерию (и один из критериев - «какой идентификатор объекта / агрегата интересует меня» => streamId снова ).
1034 * Воспроизведение *
При воспроизведении событий для создания новых проекций у вас просто есть несколько подписчиков на тип события (и, вероятно, версию), и если это для вас, вы читаете полный оригинал документа события, вы обрабатываете его, рассчитать и обновить прогноз. И если событие не для вас, просто пропустите его.
При воспроизведении вы восстанавливаете совокупные таблицы чтения, которые вы хотите перестроить, в известный начальный набор (возможно, «все пусто»), затем выбираете один или несколько потоков, выбираете события в хронологическом порядке и итеративно обновляете состояние агрегаты.
Окей ...
Все это кажется мне разумным. Пока новостей нет.
Вопрос
Но ... у меня сейчас есть короткое замыкание в моей голове ... Это такое простое короткое замыкание, что, вероятно, ответ настолько очевиден, что я буду чувствовать глупость из-за того, что не смогу увидеть его сейчас ...
Что происходит ... если событие "одинаково важно" для двух агрегатов разных типов (при условии, что они находятся в одном и том же ограниченном контексте) или даже если оно ссылается на два экземпляра одного и того же типа агрегата.
Пример 2 одинаково важных разных агрегатов:
Представьте, что вы работаете в железнодорожной отрасли, и у вас есть эти совокупности:
Locomotive
Wagon
На мгновение представьте, что один локомотив может перевозить 0 или 1 вагон, но не так много вагонов.
И у вас есть эти команды:
Attach( locomotiveId, wagonId )
Detach( locomotiveId, wagonId )
Присоединение может быть отклонено, если локомотив и вагон уже были прикреплены к чему-либо, и отсоединение может быть отклонено, если команда выдается, когда они не присоединены.
События, очевидно, соответствуют:
AttachedEvent( locomotiveId, wagonId )
DetachedEvent( locomotiveId, wagonId )
Q:
Какой там идентификатор потока? и локомотив, и вагон имеют одинаковое значение, это не событие "локомотива" или "вагона". Это событие домена, которое затрагивает этих двоих! Какой из них является streamId и почему?
Пример с двумя агрегатами одного типа
Скажите, что проблема отслеживания. У вас есть этот агрегат:
Issue
И эти команды:
MarkAsRelated( issueAId, issueBId )
UnmarkAsRelated( issueAId, issueBId )
И отметка отклоняется, если отметка уже была, и снимается отметка, если предыдущей отметки не было.
И те события:
MarkedAsRelatedEvent( issueAId, issueBId )
UnmarkedAsRelatedEvent( issueAId, issueBId )
Q:
Тот же вопрос здесь: Дело не в том, что отношения «принадлежат» проблеме А или В. Они либо связаны, либо нет. Но его двунаправленный. Если A относится к B, то B относится к A. Что здесь за идентификатор потока и почему?
История написана один раз
В любом случае, я не вижу создания ДВУХ событий по одному для каждого. Это вопрос калькуляторов ...
Если мы видим определение «история» (вообще не в компьютерах!), Оно говорит «последовательность событий, которые произошли». В свободном словаре написано: «Хронологическая запись событий» (https://www.thefreedictionary.com/history)
Поэтому, когда идет война между социальной группой A и социальной группой B и, скажем, B бьет A, вы не пишете 2 события: lost(A)
и won(B)
. Вы просто пишете одно событие warFinished( wonBy:B, lostBy:A )
.
Вопрос
Итак, как вы обрабатываете потоки событий, когда событие влияет на несколько объектов одновременно, и это не значит, что оно «принадлежит» одному, а другое является дополнением к этому, но оно действительно равно обоим?