...

Работа с элементом приложения в параллельных задачах

Тема в разделе "Примеры решений и дополнительных модулей", создана пользователем krapivina, 21 мар 2022.

  1. krapivina

    krapivina Новичок

    Хочу рассказать небольшой кейс про одновременное редактирование элемента приложения.

    Представим ситуацию:

    В системе создано приложение, состоящее из переменных – «Тема» и «Описание». Два пользователя в системе одновременно открыли элемент этого приложения на редактирование. Первый пользователь вносит изменения в поле «Тема» и нажимает на кнопку «Сохранить», после чего видит, что его изменения успешно применились. Второй пользователь в это время вносит изменения в поле «Описание» и также нажимает кнопку «Сохранить», в результате в поле «Описание» мы видим новое значение, а в поле «Тема» - значение до редактирования первым пользователем.

    При одновременном редактировании элемента приложения несколькими пользователями будет сохранена версия того пользователя, который последним нажмет на кнопку «Сохранить».

    Здесь все понятно. Но недавно мы столкнулись с одним интересным кейсом.

    Приложение «Бронирование специалистов». В приложении есть несколько полей, в том числе две таблицы: «Данные по бронированию (план)» и «Данные по бронированию (факт)». Пользователь создает элемент приложения, заполняет таблицу с плановыми данными и запускает процесс. В процессе с помощью сценария отбираются данные по каждой строке таблицы «Данные по бронированию (план)», после чего эти данные передаются в подпроцесс.

    [​IMG]

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

    [​IMG]

    При этом все подпроцессы запускаются асинхронно, и в итоге мы имеем несколько параллельно созданных задач у разных пользователей. Как только пользователь выполняет задачу, с помощью сценария в элемент приложения в таблицу «Данные по бронированию (факт)» добавляется строка. В результате, сколько экземпляров подпроцесса было запущено, столько и строк должно быть добавлено в данную таблицу.

    Итак, пользователь заполняет карточку приложения, добавляет в таблицу «Данные по бронированию (план)» 2 строки и сохраняет данные. Запускается основной процесс.

    [​IMG]

    Двум пользователям поступили задачи в рамках экземпляров запущенного подпроцесса.

    [​IMG]

    Пользователи одновременно открывают эти задачи.

    Первый пользователь заполняет данные и нажимает на кнопку «Готово».

    [​IMG]

    Открывает карточку приложения и видит, что после выполнения задачи добавилась строка в таблицу «Данные по бронированию (факт)».

    [​IMG]

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

    [​IMG]

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

    [​IMG]

    То есть мы получили в итоге одну строку в таблице вместо двух ожидаемых.

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

    [​IMG]

    Как мы видим, среди свойств приложения на форму задачи не вынесена таблица «Данные по бронированию (факт)». Несмотря на это при выполнении задачи сохраняются все свойства элемента приложения, в том числе эта таблица. Пользователи открыли задачи, когда в карточке приложения таблица была еще пустой. После выполнения задачи первым пользователем система сначала сохранила весь контекст приложения, каким он был на момент открытия задачи, а после сценарий добавил строку в таблицу. У второго пользователя в открытой задаче все еще была версия приложения с пустой таблицей. Когда он выполняет задачу, система сохраняет контекст приложения именно с этой версией, поэтому на момент добавления новой строки таблица снова оказывается пустой.

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

    Варианты обхода данной ситуации:

    • Не использовать параллельные задачи (асинхронный запуск подпроцесса), если это возможно.
    • Не выносить вложенные свойства приложения на форму задачи. Можно продублировать их в контекст процесса и на форму задачи вынести уже поля из контекста процесса.

    Если на форму обычной задачи (не параллельной) вынесены вложенные свойства приложения, то нужно также не забывать, что кто-то из пользователей может начать редактировать элемент приложения в момент, когда другой пользователь будет выполнять задачу. В таком случае также будут внесены изменения только от того, кто последним их внес.