Как Trello хранит сгенерированные действия из обновлений других документов (досок, карточек) в MongoDB без атомарных транзакций? - PullRequest
0 голосов
/ 14 апреля 2019

Я разрабатываю одностраничное веб-приложение, которое будет использовать базу данных документов NoSQL (например, MongoDB), и я хочу генерировать события, когда я изменяю свои сущности.

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

Скажем, например, что у меня есть коллекция «События» и коллекция «Карты», как у Trello.Когда я изменяю описание карты из коллекции «Карты», должно генерироваться событие «CardDescriptionChanged».

Проблема в том, что в случае сбоя или какой-либо ошибки между сохранением изменений в коллекции 'Cards' и добавлением события в коллекцию 'Events' это событие не будет сохраняться, и я не хочучто.

Я провел некоторое исследование по этой проблеме, и большинство людей предложили бы использовать один из нескольких подходов:

  1. Не используйте MongoDB, используйте SQLвместо базы данных (я не хочу этого)

  2. Использовать источник событий.(Это создает сложность, и я хочу очистить старые события в какой-то момент, поэтому я не хочу сохранять все события в памяти. Теперь я могу использовать моментальные снимки и удалять более старые события из точки моментального снимка, но в этом есть сложностьрешение)

  3. Поскольку ошибки такого рода, вероятно, не будут происходить слишком часто, просто игнорируйте их и рискуйте иметь события, которые не будут сохранены (я тоже этого не хочу)

  4. Использовать процессор событий / команд / действий.Сохраните команды / действия, такие как «ChangeCardDescription», и используйте процессор, который будет их обрабатывать и обновлять сущности.

Я рассмотрел вариант 4, но возникает пара вопросов:

  • Как мне управлять параллелизмом?

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

  • Сообщения об ошибках и обработка ошибок.

Если этот процесс асинхронный, я должен управлять сообщением об ошибках клиенту.А также я должен удалить или пометить команды, которые потерпели неудачу.

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

Поскольку Trello использует MongoDB и генерирует действия ('DeleteCardAction', 'CreateCardAction') с изменениями сущностей (Cards, Boards ..)) Мне было интересно, как они решают эту проблему?

1 Ответ

1 голос
/ 15 апреля 2019

Создайте новую коллекцию с именем FutureUpdates. Запишите запланированные обновления в коллекцию FutureUpdates с одним документом, определяющим изменения, которые вы планируете внести в карты, и события, которые вы планируете генерировать. Эта вставка будет атомарной.

Теперь возьмите [ChangeStream][1] из коллекции FutureUpdates, это даст вам поток обновлений, которые вам нужно сделать. Возьмите каждый документ из потока изменений и примените обновления. Наконец, обновите документ в FutureUpdates, чтобы пометить его как завершенный. Опять же, это обновление будет атомным.

При применении обновлений к событиям и картам обязательно включайте objectID документа, используемого для создания обновления, в FutureUpdates.

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

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

Фактически, вы постоянно атомарно обновляете документ для каждого изменения в FutureUpdates, чтобы отслеживать прогресс. После завершения обновления вы можете заархивировать старые документы или просто удалить их.

...