Обработка сбоя БД во время проецирования в cqrs

Мы создаем систему с использованием CQRS. Наши прогнозы в mongodb. Мы сталкиваемся с некоторыми случаями. У нас есть событие, скажем, OrderCreated. Нам нужно создать последовательный order_no, например, № 3, № 4 и т. Д. Мы могли бы использовать проекцию и сохранить последовательность в таблице, затем вызвать метод upsert. и получить новый номер. Отправьте новую команду: GenerateOrderNumber. Теперь до этого поста произошел сбой оборудования. Если мы повторим попытку, у нас будет другой номер. Это не хорошо. Как решить такой вариант использования в cqrs.

2 ответа

Решение

Наши прогнозы в mongodb <...>
Теперь, прежде чем это сообщение принято сбой оборудования

Скорее всего, описанная проблема не связана с CQRS или EventSoucring, а связана с хранилищем проекций, о котором речь шла о MongoDB выше.

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

Лучший выбор - это собственные транзакции MongoDB, которые доступны с версии 4.0 - https://docs.mongodb.com/manual/core/transactions/ - и ваш код будет выглядеть следующим образом:

session.startTransaction( … );
try {
  const lastNo = await eventsCollection.findOne( ... )
  await eventsCollection.insertOne( …, lastNo +1 )
  session.commitTransaction()
} catch (error) {
  session.abortTransaction()
}

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

Вы должны выполнять все действия через события, даже генерируя последовательность №. В вашем случае я предлагаю вам использовать сагу:

  • построить прогноз для генерации order_no
  • запустить новое событие OrderCreated (после этого у вас будет Order Aggregate с уникальным идентификатором)
  • сага, прослушивание этого события, запуск события GenerateOrderNo (получить следующий бесплатный номер из проекции)

В этом случае, каждый раз, когда вы спрашиваете новый order_no после сбоя, он будет таким же.

Поправьте меня пожалуйста, если я вас неправильно понял.

Другие вопросы по тегам