Архитектура и системные требования / Предотвращение конфликта при сохранении данных

Предотвращение конфликта при сохранении данных

Когда несколько пользователей одновременно редактируют один и тот же элемент приложения, во время сохранения может возникнуть конфликт. Это приведёт к тому, что изменения не сохранятся, данные потеряются, и в системе будет отображаться неактуальная информация.

Для решения этой проблемы реализовано:

  1. Атомарное изменение атрибутов — сохраняются только отредактированные поля, а не весь элемент целиком.
  2. Контроль конфликтов и блокировка записи изменений — при наличии конфликта пользователь получает уведомление о необходимости обновить страницу перед повторным сохранением, кнопка сохранения временно становится неактивной.
  3. Проверка версий элемента на сервере — элемент содержит уникальный идентификатор версии __version, который обновляется при каждом сохранении данных.

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

  • если версии совпадают во всём, кроме внесённых пользователем изменений, то версия на сервере обновляется;
  • если версии не совпадают, значит элемент был изменён параллельно. Корректировки пользователя отклоняются с ошибкой «version inconsistency: collision», он увидит уведомление о конфликте с просьбой обновить страницу. Кнопка сохранения блокируется;
  • если пользователь изменил значение полей, но затем вернул прежние данные и сохранил элемент, то на сервер возвращается версия без фактических изменений, значение атрибута остаётся текущим.

Механизм обработки конфликтов при сохранении применяется:

  • когда пользователи вручную открывают элемент на редактирование;
  • при изменении элемента в рамках бизнес-процесса, исполнения скрипта или методов Web API.

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

Начало примера

Обратите внимание на следующие ограничения:

  • предотвращение конфликтов доступно только для пользовательских свойств приложения. При изменении системных полей, например статуса, уведомление не отправляется;
  • в системе прав доступа и при удалении элемента отслеживание изменений не поддерживается;
  • одновременное редактирование данных в рамках массовых действий не обрабатывается.

Конец примера

Примеры предотвращения конфликтов при сохранении элемента

Кейс 1. Пользователи одновременно редактируют элемент

  1. Пользователь А открывает карточку клиента и редактирует поле Номер телефона.
  2. В это время пользователь Б открывает ту же карточку и редактирует поле Email.
  3. Пользователь А сохраняет свои изменения.
  4. В результате пользователь Б получает уведомление «Элемент изменен! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить». Кнопка Сохранить временно блокируется.

Пользователь Б обновляет карточку и видит актуальный номер телефона, введённый пользователем А. Он может повторно ввести и сохранить новый email.

Кейс 2. Элемент редактируется одновременно вручную и в рамках задачи бизнес-процесса

  1. В системе настроен бизнес-процесс, в рамках которого пользователю А приходит задача на изменение данных элемента. Он редактирует поле Email.
  2. Параллельно пользователь Б открывает карточку того же элемента, редактирует поле Телефон и сохраняет изменения.
  3. Пользователь А получает уведомление «Элемент изменен! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить». Кнопка Сохранить временно блокируется.

Пользователь А обновляет карточку задачи, видит актуальный номер, введённый пользователем Б. Он повторно вводит и сохраняет новый email.

Кейс 3. Элемент редактируется одновременно вручную и в рамках исполнения скрипта в бизнес-процессе

  1. Пользователь А открывает карточку клиента и редактирует поле Email.
  2. Параллельно пользователь Б запускает бизнес-процесс, в рамках которого выполняется скрипт для автоматического изменения электронной почты того же клиента.
  3. Пользователь А сохраняет изменения.
  4. Если экземпляр процесса ещё не выполнился, он завершится с ошибкой «version inconsistency: collision». На сервере сохранятся данные, введённые пользователем А.

Если пользователь А сохранил свои изменения после отработки скрипта, то он получит уведомление «Элемент изменен! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить». Кнопка Сохранить временно заблокируется.

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

Важно: в этом кейсе для корректной работы блока Скрипт в его настройках на вкладке Обработка ошибок:

  • отключите опцию Повторить выполнение, чтобы избежать бесконечных попыток перезаписи данных;
  • включите опцию Оповещение и выберите получателя уведомления об ошибке. Администратор сможет решить её в мониторе ошибок и, например, перезапустить процесс.

Кейс 4. Элемент изменяется одновременно вручную и в рамках выполнения методов Web API

  1. Пользователь А открывает карточку клиента и редактирует поле Номер телефона.
  2. В это же время от внешней системы или другого пользователя через Web API отправляется запрос на обновление этого же поля в той же карточке.
  3. Пользователь А сохраняет изменения.
  4. Если запрос от Web API ещё не завершился, в ответ вернётся ошибка «version inconsistency: collision». На сервере сохранятся данные, введённые пользователем А.

Если пользователь А сохранил свои изменения после выполнения запроса, то ему придёт уведомление «Элемент изменен! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить», кнопка Сохранить временно заблокируется.

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

Кейс 5. Элемент одновременно редактируется вручную и в рамках исполнения скрипта в виджете

  1. Пользователь А открывает карточку клиента и редактирует поле Номер телефона.
  2. Параллельно пользователь Б в той же карточке нажимает кнопку, которая запускает скрипт для автоматического изменения номера клиента.
  3. Пользователь А сохраняет изменения.
  4. Если скрипт ещё не выполнился, вернётся ошибка «version inconsistency: collision». На сервере сохранятся данные, введённые пользователем А.

Если пользователь А сохранил свои изменения после исполнения скрипта, то ему придёт уведомление «Элемент изменен! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить», кнопка Сохранить временно заблокируется.

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

Обработка ошибок в скриптах с помощью try – catch

Чтобы при конфликте сохранений скрипты не завершались ошибкой, вы можете использовать конструкцию для обработки ошибок try – catch.

Рассмотрим кейс:

  1. Пользователь А открывает карточку клиента и редактирует поле Номер телефона.
  2. Параллельно пользователь Б запускает бизнес-процесс со скриптом, в рамках исполнения которого получает задачу на изменение этого же элемента и вводит новый номер.
  3. Пользователь А сохраняет изменения.
  4. Если скрипт ещё не завершился, вернётся ошибка «version inconsistency: collision». Сработает try – catch, ошибка автоматически обработается и скрипт продолжит выполняться. На сервере сохранятся данные, введённые пользователем Б, а пользователь А получит уведомление о конфликте.