﻿# Предотвращение конфликта при сохранении данных

> [HTML Version](preventing-data-save-conflict.html)

Когда несколько пользователей одновременно редактируют один и тот же элемент приложения, во время сохранения может возникнуть конфликт. Это приведёт к тому, что изменения не сохранятся, данные потеряются, и в системе будет отображаться неактуальная информация. 

Для решения этой проблемы реализовано:

1. Атомарное изменение атрибутов — сохраняются только отредактированные поля, а не весь элемент целиком. 

2. Контроль конфликтов и блокировка записи изменений — при наличии конфликта пользователь получает уведомление о необходимости обновить страницу перед повторным сохранением, кнопка сохранения временно становится неактивной.

3. Проверка версий элемента на сервере — элемент содержит уникальный идентификатор версии \[OBJECT\], который обновляется при каждом сохранении данных. 

Когда пользователь открывает карточку элемента, с сервера загружается текущее значение атрибута. После того как пользователь завершил редактирование и сохранил элемент, на сервере происходит проверка версий:

- если версии совпадают во всём, кроме внесённых пользователем изменений, то версия на сервере обновляется;

- если версии не совпадают, значит элемент был изменён параллельно. Корректировки пользователя отклоняются с ошибкой «version inconsistency: collision», он увидит уведомление о конфликте с просьбой обновить страницу. Кнопка сохранения блокируется;

- если пользователь изменил значение полей, но затем вернул прежние данные и сохранил элемент, то на сервер возвращается версия без фактических изменений, значение атрибута остаётся текущим.

Механизм обработки конфликтов при сохранении применяется:

- когда пользователи вручную открывают элемент на редактирование;

- при изменении элемента в рамках бизнес-процесса, исполнения скрипта или методов Web API. 

Чтобы активировать защиту от конфликтов, в [настройках приложения](360007708691.md#data-save-conflict) включите опцию **Предотвращать конфликты сохранений**. 

````
Начало примера

````
Обратите внимание на следующие ограничения:

- предотвращение конфликтов доступно только для пользовательских свойств приложения. При изменении системных полей, например статуса, уведомление не отправляется;

- в системе прав доступа и при удалении элемента отслеживание изменений не поддерживается;

- одновременное редактирование данных в рамках массовых действий не обрабатывается.

````
Конец примера

## ````
Примеры предотвращения конфликтов при сохранении элемента

**Кейс 1. Пользователи одновременно редактируют элемент**

1. Пользователь А открывает карточку клиента и редактирует поле **Номер телефона**.

2. В это время пользователь Б открывает ту же карточку и редактирует поле **Email**.

3. Пользователь А сохраняет свои изменения.

4. В результате пользователь Б получает уведомление «Элемент изменен\! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить». Кнопка **Сохранить** временно блокируется.

Пользователь Б обновляет карточку и видит актуальный номер телефона, введённый пользователем А. Он может повторно ввести и сохранить новый email.

**Кейс 2. Элемент редактируется одновременно вручную и в рамках задачи бизнес-процесса**

1. В системе настроен бизнес-процесс, в рамках которого пользователю А приходит задача на изменение данных элемента. Он редактирует поле **Email**.

2. Параллельно пользователь Б открывает карточку того же элемента, редактирует поле **Телефон** и сохраняет изменения. 

3. Пользователь А получает уведомление «Элемент изменен\! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить». Кнопка **Сохранить** временно блокируется.

Пользователь А обновляет карточку задачи, видит актуальный номер, введённый пользователем Б. Он повторно вводит и сохраняет новый email.

**Кейс 3. Элемент редактируется одновременно вручную и в рамках исполнения скрипта в бизнес-процессе**

1. Пользователь А открывает карточку клиента и редактирует поле **Email**.

2. Параллельно пользователь Б запускает бизнес-процесс, в рамках которого выполняется скрипт для автоматического изменения электронной почты того же клиента.

3. Пользователь А сохраняет изменения.

4. Если экземпляр процесса ещё не выполнился, он завершится с ошибкой «version inconsistency: collision». На сервере сохранятся данные, введённые пользователем А. 

Если пользователь А сохранил свои изменения после отработки скрипта, то он получит уведомление «Элемент изменен\! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить». Кнопка **Сохранить** временно заблокируется. 

Пользователь А обновляет карточку, видит актуальные данные и может повторно ввести и сохранить email. 

**Важно:** в этом кейсе для корректной работы блока **Скрипт** в его [настройках](360027203731.md#error-handling-tab) на вкладке **Обработка ошибок**:

- отключите опцию **Повторить выполнение**, чтобы избежать бесконечных попыток перезаписи данных;

- включите опцию **Оповещение** и выберите получателя уведомления об ошибке. Администратор сможет решить её в [мониторе ошибок](error_monitor.md) и, например, перезапустить процесс. 

**Кейс 4. Элемент изменяется одновременно вручную и в рамках выполнения методов Web API**

1. Пользователь А открывает карточку клиента и редактирует поле **Номер телефона**.

2. В это же время от внешней системы или другого пользователя через Web API отправляется запрос на обновление этого же поля в той же карточке. 

3. Пользователь А сохраняет изменения.

4. Если запрос от Web API ещё не завершился, в ответ вернётся ошибка «version inconsistency: collision». На сервере сохранятся данные, введённые пользователем А. 

Если пользователь А сохранил свои изменения после выполнения запроса, то ему придёт уведомление «Элемент изменен\! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить», кнопка **Сохранить** временно заблокируется.

Пользователь А обновит карточку, увидит актуальные данные и сможет повторно ввести и сохранить номер. 

**Кейс 5. Элемент одновременно редактируется вручную и в рамках исполнения скрипта в виджете**

1. Пользователь А открывает карточку клиента и редактирует поле **Номер телефона**.

2. Параллельно пользователь Б в той же карточке нажимает кнопку, которая запускает скрипт для автоматического изменения номера клиента. 

3. Пользователь А сохраняет изменения.

4. Если скрипт ещё не выполнился, вернётся ошибка «version inconsistency: collision». На сервере сохранятся данные, введённые пользователем А. 

Если пользователь А сохранил свои изменения после исполнения скрипта, то ему придёт уведомление «Элемент изменен\! Чтобы избежать потери данных, обновите страницу, прежде чем продолжить», кнопка **Сохранить** временно заблокируется.

Пользователь А обновит карточку, увидит актуальные данные и сможет повторно ввести и сохранить номер. 

## Обработка ошибок в скриптах с помощью try – catch

Чтобы при конфликте сохранений скрипты не завершались ошибкой, вы можете прописать логику обработки ошибок в конструкции \[OBJECT\]. 

Рассмотрим кейс:

1. Пользователь А открывает карточку клиента и редактирует поле **Номер телефона**.

2. Параллельно пользователь Б запускает бизнес-процесс со скриптом, в рамках исполнения которого меняет номер телефона того же клиента.

3. Пользователь А сохраняет изменения.

4. Если скрипт ещё не завершился, на сервере сохранятся данные, введённые пользователем А. Скрипт при этом продолжит выполняться, так возвращённая ошибка «version inconsistency: collision» автоматически обработается с помощью \[OBJECT\].