Обработка сбоя БД во время проецирования в 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 после сбоя, он будет таким же.
Поправьте меня пожалуйста, если я вас неправильно понял.