Окружение: bpmonline 7.2

Опишу вкратце задумку:
1. На странице пользователь меняет какие-то поля у объекта жмет кнопку сохранения (это сейчас уже работает).
2. На изменение статуса (было Новое, стало Изменено) создан бизнес-процесс, в котором реализована логика обработки объекта при изменении (это сейчас уже работает).
3. Теперь требуется вызвать внешнюю процедуру (связь баз по linked server), которая в свою очередь должна получить данные по объекту и не только.

И вот как раз с третьим пунктом возникла проблема - внешняя процедура отваливается по таймауту. В ходе разбора этой проблемы, удалось выяснить следующее (поправьте если не прав):
1. бизнес-процесс вызывается в том же потоке, что и сохранение объекта
2. при этом все это происходит в одной транзакции
3. вызывая внешнюю процедуру, которая обращается в тем же данным, получаем неявную блокировку данных. Т.е. при выполнении запросов с одной базы к другой открывается своя транзакция, которая блокируется уже открытой транзакции.

Проблема "решается" если вызов вызвать в отдельном потоке (реализация через Task) - тогда транзакции закрываются в основном потоке и не мешают выполнению запроса. Или принудительно закрыть транзакцию. Но это на мой взгляд не верное решение данной проблемы. Так как отрабатывает бизнес-процесс-2 по изменению другого поля, которое изменяется в "вызове" и в результате бизнес-процесс-2 не запускается.

Можете ли вы подсказать, что можно в данном случае сделать? Может быть можно вызвать бизнес-процесс на изменения поля уже после закрытия транзакции основной, в рамках которой и изменяется объект.

поменял тему для привлечения внимания

Нравится

6 комментариев

Еще момент, если реализовывать через Task, т.е. в отдельном потоке, то периодически возникает ошибка:

 file: http://****/0/core/4ec8ac09273bab8d86ca61871b5b3a39/combined/all-combined.js
 line: 460
 message: Uncaught The transaction operation cannot be performed because there are pending requests working on this transaction. 

Что, как я понимаю, указывает на проблему с транзакциями/соединениями. Их кол-во не совпадает с тем, что должно быть. Хотя я явно транзакции не открываю и не коммичу.

А что если часть логики с вызовом сторонней процедуры вынести в AFTER UPDATE/INSERT trigger?

IF UPDATE(StatusID)
BEGIN
  exec stor.proc
END

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

Тут скорее вопрос следующий возникает - можно ли где-то почитать/узнать как реализован вызов процессов по изменению поля у объекта? Какая именно работа в этом случае происходит с транзакциями?
Так как я могу лишь предполагать, основываясь на результате работы, что процессы-подписчики вызываются в том же потоке и в той же транзакции, что и метод обновления объекта, вызываемый со страницы. Если это так, то можно ли как-то на это повлиять?

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

Здравствуйте, Александр!

Процессы-подписчики действительно вызываются в том же потоке. Для создания нового потока используйте элемент "Таймер". Поставьте минимальное значение (1 секунда). Запуск элементов, следующих после таймера, будет осуществлятся уже в новом потоке.

Спасибо, за ответ. Попробую сделать через таймер.

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

Показать все комментарии