Обновление нескольких агрегатов с помощью JOliver EventStore - PullRequest
5 голосов
/ 16 ноября 2011

У меня вопрос по поводу обновлений нескольких агрегатов в одной транзакции с использованием хранилища событий JOliver .Как я понимаю, каждый агрегат должен иметь свой собственный поток событий.Теперь, в то время как многие обработчики команд будут загружать только один агрегат и обновлять только этот агрегат (т.е. сохранять события для этих агрегатов), я могу представить, что будут обработчики команд, которым необходимо обновить несколько агрегатов.И, конечно, я хотел бы сделать это транзакционным способом.

Тем не менее, я не понимаю, как я мог бы сделать это с Event Store.Сохранение событий осуществляется путем вызова CommitChanges() в потоке событий.Если у нас есть несколько агрегатов для обновления, будет иметь несколько потоков событий и, следовательно, несколько вызовов на CommitChanges().Единственный способ сделать эту транзакцию - это обернуть ее в TransactionScope, но это не имеет особого смысла, поскольку базовая технология хранения может не поддерживать транзакции.В итоге я получаю этот код, который определенно не то, что я ищу:

        Guid aggregateGuid1 = Guid.NewGuid();
        Guid aggregateGuid2 = Guid.NewGuid();
        Guid commitGuid = Guid.NewGuid();

        var stream = store.OpenStream(aggregateGuid1, 0, int.MaxValue);
        stream.Add(new EventMessage() { Body = new MonitorDisabled { MonitorGuid = aggregateGuid1, User = "A" } });
        stream.CommitChanges(commitGuid);

        stream = store.OpenStream(aggregateGuid2, 0, int.MaxValue);
        stream.Add(new EventMessage() { Body = new MonitorEnabled { MonitorGuid = aggregateGuid2, User = "B" } });
        // Can't commit twice with the same commit id, what if fails after first one? No way for the store to know it had to write the second part of the commit.
        stream.CommitChanges(commitGuid);

Это заставляет меня чувствовать, что я что-то упускаю из-за того, как следует использовать хранилище событий.Может ли кто-нибудь помочь мне здесь?Большое спасибо!

Ответы [ 3 ]

8 голосов
/ 16 ноября 2011

Агрегат определяет границу транзакции.

Если вам нужно выполнить кросс-агрегатные транзакции, вы должны проверить свои агрегаты и, возможно, перепроектировать их.

В тех случаях, когда операция (команда) влияет на несколько агрегатов, и вы уверены, что ваши агрегаты хорошо спроектированы и соответствуют реальным границам согласованности в вашем домене, возможная согласованность может быть тем, чем вы являетесь находясь в поиске. Просто отправьте команду для каждого агрегата и получите две транзакции, по одной для каждой из них. Если вы не чувствуете, что последовательность подходит для вашего случая, я боюсь, что она вернулась к чертежной доске.

3 голосов
/ 16 ноября 2011

Я не могу говорить за Джона Оливера, но я думаю, что ответ "нет".Агрегаты являются границами транзакций.Если вам нужно координировать фиксацию нескольких агрегатов, вам нужен явный процесс координации, такой как сага, который будет выполнять и при необходимости отменять соответствующие события.

0 голосов
/ 29 ноября 2011

Иногда в этих сценариях проще использовать преимущества распределенных транзакций, если ваша инфраструктура их поддерживает.

TransactionScope с EventStore:

EventStore по умолчанию подавляет любую созданную внешнюю транзакцию NServiceBus до внесения изменений в базу данных. Однако если вы используете очередь и базу данных, которые поддерживают распределенную транзакции (MSMQ, SQL Server, Raven и т. д.), то вы можете изменить TransactionScopeOption EventStore для Обязательный. Это обеспечит EventStore зачисляется в окружающую транзакцию, из которой будет распространяться с использованием MSDTC, а также очереди сообщений и базы данных будет синхронизирован. - Документация РЭШ

Кросс-документные транзакции с RavenDB:

Вы будете извлекать информацию из моих мертвых, холодных, сломанных рук - Айенде

...