Обработка сбоя БД во время проецирования в cqrs - PullRequest
0 голосов
/ 22 февраля 2019

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

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Наши прогнозы представлены в виде 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, транзакции все еще можно использовать.Но вместо использования встроенного оператора вы должны вручную записать журнал транзакций, а после повторного подключения к базе данных выполнить мониторинг прерванных транзакций и отменить их вручную через журнал.

0 голосов
/ 27 февраля 2019

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

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

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

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

...