Источник событий: напишите событие до или после обновления модели.

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

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

Я использую Akka Actors, поэтому обработка выполняется последовательно для каждого события/сообщения. В настоящее время у меня нет базы данных, вместо этого я буду сохранять все события в журнале событий, а затем сохранять агрегированное состояние всех событий в модели, хранящейся в памяти. Запросы все против этой модели, можете считать это кешем.

Пример

Создание нового пользователя:

  1. Подтвердить, что пользователь не существует в модели
  2. Сохранить событие в журнале
  3. Обновить модель (в памяти)

Если шаг 3 прерывается, я все еще сохраняю свое событие, поэтому я могу воспроизвести его позже. Если шаг 2 сломается, я тоже справлюсь с этим изящно.

Это нормально, но поскольку шаг 2 связан с вводом-выводом, я решил, что должен выполнять ввод-вывод в отдельном действующем субъекте, чтобы освободить первый действующий элемент для запросов:

Обновление пользователя при разрешении запросов (A0 = актор внешнего интерфейса/графического интерфейса, A1 = актор процессора, A2 = актор IO, E = шина событий).

  1. (A0->E->A1) Событие публикуется для обновления пользователя 'U1'. Подтвердите, что пользователь «U1» существует в модели
  2. (A1->A2) Сохранение события в журнале (отдельное действующее лицо)
  3. (A0->E->A1->A0) Запрос для профиля пользователя 'U1'
  4. (A2->A1) Событие теперь сохраняется, продолжайте обновлять модель
  5. (A0->E->A1->A0) Запрос профиля пользователя 'U1' (теперь возвращает свежие данные)

Это привлекательно, поскольку запросы могут обрабатываться, пока ввод-вывод происходит в своем собственном темпе.

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

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

Если что-то непонятно, напишите комментарий.


person Magnus    schedule 15.10.2012    source источник
comment
Это не имеет значения, если вы знаете, что не публикуете событие, не зафиксировав свои изменения в модели или не обновив модель и не опубликовав событие. Многие платформы предоставляют такой транзакционный контекст, включая NServiceBus, используя MSDTC, но есть и другие способы достижения этого. На самом деле никто не может дать вам конкретных ответов на этот вопрос, это действительно зависит от вашей текущей инфраструктуры.   -  person MeTitus    schedule 12.08.2013


Ответы (1)


Асинхронный ввод-вывод может сосуществовать с транзакционными обновлениями. Если после команды отправить "ACK" или "NACK", то можно понять, произошло это или нет. В распределенной или действительно асинхронной модели, скорее всего, "NACK" будет исходить как от явных сбоев, так и от тайм-аутов.

person Sebastian Good    schedule 17.10.2012
comment
В системе Windows вы имеете в виду использование MSDTC для координации этой транзакции, верно? Что касается OP, команды в настоящей асинхронной среде попадают в очередь FIFO, поэтому я не уверен, как вы подходите к транзакциям и обновляете модель в контексте асинхронной команды в той же корзине. Я бы понял транзакцию, группирующую обновление в модели и событие, создаваемое в исходящей очереди, но не команды. - person MeTitus; 12.08.2013