2016-12-06 7 views
1

У меня есть следующая задача:CQRS и команда дребезг

  1. Наша текущая архитектура Web SPA с CQRS и MVVM. У нас есть команды , запросы и SingnalR как шина сообщений.
  2. Пользователи могут выбирать, перемещать, изменять размеры divs на одной рабочей области из нескольких веб-браузеров одновременно.
  3. Каждый div привязан к соответствующей ViewModel. Каждый ViewModel имеет собственный запрос для обновления. Каждый ViewModel подписался на бизнес-события и обновил все состояние после него.

Позволяет изображение, которое пользователь выполняет следующие действия:

  1. Выберите Див (SelectWidgetCommand посланный)
  2. Перемещение дел до х = 10. (ChangePositionCommand отправлено)
  3. Переместить div на x = 100. (ChangePositionCommand пересылаются)

Проблема заключается в том, что команды являются пожаро- и забыть, и пользователь может получить событие WidgetSelectedEvent во время шага 3, но ChangePositionCommand не могут быть обработаны еще. Таким образом, пользователь получит старую позицию x, и div переместится в прежнее положение.

Какова наилучшая практика для решения таких проблем?

Что мы сейчас делаем, так это разделение DivViewModel на два div: SelectionViewModel, PositionViewModel. Каждый ViewModel имеет собственный запрос для обновления и различные события для обработки. Также мы рассматриваем использование буфера debounce и roll для обработки команд.

+0

Ваше решение кажется хорошим. Разделите на более мелкие модели, каждый из которых синхронизируется через определенное подмножество событий. Другим решением, которое я мог бы подумать, было бы иметь одну модель, но создавать сопоставления атрибутов событий (например, map ViewModel.position to ChangePositionCommand.position). До тех пор, пока ваши события не будут получены из строя, которые должны работать. Кстати, странно, что команда selecton обрабатывается на стороне сервера. Не может ли состояние выбора существовать только на клиенте? – plalx

+0

@plalx У нас есть тот же выбор для всех пользователей, которые работают в одной рабочей области –

+0

Разве это не создает ненужного спора, который почти предотвращает сотрудничество? Что делать, если выбор будет изменен пользователем B, в то время как пользователь A пытался выполнить команду по его первоначальному выбору? – plalx

ответ

1

Возможно, вы захотите ознакомиться с докладом Грега Янга на странице occasionally connected systems.

Проблема заключается в том, что команды являются пожаро- и забыть

Как вы понимаете, «огонь и забыть»? Если модели не разрешено отклонять команды, отправленные на нее, то отправляемые сообщения: события, а не команды.

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

Compare-And-Set, а не Set.

В своей простейшей форме команды определяют начальную версию совокупности, которую они собираются изменить, во многом аналогично тому, как в условных запросах в HTTP указывается preconditions on the resource. В случае состояния гонки с несколькими командами, пытающимися изменить одну и ту же часть модели, одна команда победит, а проигравший будет тривиально отклонен.

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

Альтернативный подход заключается в том, чтобы позволить как выполнять запись, так и принимать конфликт. Подумайте о том, как работает система управления версиями: я сделал историю 1-2-X, вы сделали историю 1-2-Y, и теперь есть две альтернативы, пока кто-то не примирит их с слиянием.

Этот подход примерно соответствует центральной точке Уди Дахана в его эссе Race Conditions Don't Exist.

Микросекундная разница во времени не должна иметь значения для основных бизнес-моделей поведения.

Если ваши взгляды строятся из списков событий (как вы описали здесь), тогда одно место для начала с CRDT списка. Марк Клепманн описывает JSON data type(hacker new commentary). Это не дает вам «никаких конфликтов», но это дает вам свойство, что два пользователя, которые видят одни и те же отдельные события, обязательно кажутся им в одном порядке (если есть проблема, тогда все видят ту же проблему).

Но подход Грега, вероятно, проще реализовать - авторы работают с локальной копией совместно используемой модели и взаимодействуют с ней, но эта общая модель является приближением, и команды, которые не могут быть согласованы с записью книги, возвращаются автору для ручного смягчения.

+0

проблема в том, что мои события не содержат данных, и я не создаю ViewModels из событий. Когда ViewModel получает событие, он отправляет запрос для обновления всего состояния ViewModel. –

Смежные вопросы