Оптимистичный Пользовательский Интерфейс, Cqrs И Eventsourcing



Оптимистичный пользовательский интерфейс, CQRS и EventSourcing

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

Другими словами, обращение к системе не должно изменить ответ. Более формально, только чистые методы, не имеющие побочных эффектов, могут возвращать значение.

Но для хорошего масштабирования разделения API на чтение/запись недостаточно.

Необходимо разделить базы данных, с которыми работает это API. Здесь нам на помощь приходит EventSourcing. Он предлагает хранить все системные события в одной базе данных, назовем ее EventStore, и строить на ее основе все остальные базы и таблицы.

Комбинация CQRS и EventSourcing существенно развязывает руки в плане балансировки нагрузки внутри системы, количества ее узлов, количества вспомогательных баз данных, использования кэширования и прочего, но в то же время усложняет логику работы.

приложение и вводит множество ограничений.

В этой статье мы рассмотрим один из нюансов проектирования клиентской части такой системы — оптимистичные обновления пользовательского интерфейса.

Для фронтенда возьмем модные React и Redux. Кстати, Redux и EventSourcing — очень похожие технологии.

Оптимистичные обновления пользовательского интерфейса уже сложно внедрить, а CQRS и EventSourcing еще больше усложняют задачу.

Как это должно работать? Давайте разберемся в этом шаг за шагом.

  1. Отправляем команду и, не дожидаясь ответа, отправляем оптимистичное событие в Redux Store. Оптимистическое событие будет содержать ожидаемые результаты сервера.

    Также на этом шаге мы запоминаем текущее состояние данных, которое изменится при событии.

  2. Ждем результата отправки команды.

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

    Если все в порядке, то ничего не делаем.

  3. Ждём, когда настоящее событие приедет из автобуса к клиенту.

    Когда это происходит, мы откатываем оптимистическое обновление и используем реальное событие.

Как это будет выглядеть на практике:
Успех Отказ


Оптимистичный пользовательский интерфейс, CQRS и EventSourcing



Оптимистичный пользовательский интерфейс, CQRS и EventSourcing



Оптимистичный пользовательский интерфейс, CQRS и EventSourcing



Оптимистичный пользовательский интерфейс, CQRS и EventSourcing

Мы опишем оптимистичный код обновления как Middleware для Redux Store:
   

const optimisticCalculateNextHashMiddleware = (store) => { const tempHashes = {}; const api = createApi(store); return next => action => { switch (action.type) { case SEND_COMMAND_UPDATE_HASH_REQUEST: { const { aggregateId, hash } = action; // Save the previous data const { hashes } = store.getState() const prevHash = hashes[aggregateId].

hash; tempHashes[aggregateId] = prevHash // Dispatch an optimistic action store.dispatch({ type: OPTIMISTIC_HASH_UPDATED, aggregateId, hash }); // Send a command api.sendCommandCalculateNextHash(aggregateId, hash) .

then( () => store.dispatch({ type: SEND_COMMAND_UPDATE_HASH_SUCCESS, aggregateId, hash }) ) .

catch( (err) => store.dispatch({ type: SEND_COMMAND_UPDATE_HASH_FAILURE, aggregateId, hash }) ); break; } case SEND_COMMAND_UPDATE_HASH_FAILURE: { const { aggregateId } = action; const hash = tempHashes[aggregateId]; delete tempHashes[aggregateId]; store.dispatch({ type: OPTIMISTIC_ROLLBACK_HASH_UPDATED, aggregateId, hash }); break; } case HASH_UPDATED: { const { aggregateId } = action; const hash = tempHashes[aggregateId]; delete tempHashes[aggregateId]; store.dispatch({ type: OPTIMISTIC_ROLLBACK_HASH_UPDATED, aggregateId, hash }); break; } } next(action); } }

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

Хотя использовать их нужно разумно и с большой осторожностью.

В некоторых случаях они могут привести к потере данных и затруднить понимание пользовательского интерфейса.

Например, оптимистичный лайк под фото — это хорошо, а оптимистичная форма оплаты — плохо.

Так что не портите ситуацию.

Удачи! Теги: #react #cqrs #eventsourceing #optimistic #JavaScript #programming #node.js #react.js

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.