В процессе эксплуатации программного продукта 1С:Документооборот (особенно редакций 2.1 и 3.0) пользователи и администраторы часто сталкиваются со специфической проблемой. При попытке открыть задачу согласования, утверждения или исполнения на форме отображается предупреждение: «Задача находится в очереди для выполнения. Выполнение задачи произойдет автоматически в ближайшее время». При этом на форме полностью отсутствуют управляющие кнопки (например, «Согласовано», «Исполнено», «Отклонить»), и даже администратор системы не может продвинуть процесс дальше.
В этой статье мы подробно разберем, как устроен механизм фонового выполнения задач, проанализируем основные причины его сбоев и рассмотрим несколько практических способов решения этой проблемы — от простых интерактивных действий до написания корректирующих программных скриптов.
Для снижения нагрузки на интерфейс пользователя и предотвращения длительных блокировок таблиц базы данных при записи сложных бизнес-процессов в системе применяется механизм отложенного выполнения. Рассмотрим эту цепочку событий по шагам:
ЗадачиДляВыполнения (в версии 3.0 — в справочник Очередь заданий) помещается запись со статусом готовности.Давайте выясним основные причины возникновения подобных ситуаций и рассмотрим эффективные методы борьбы с ними.
Прежде чем предпринимать какие-либо действия, нам необходимо понять точную причину сбоя. Для этого проанализируем поведение системы с помощью системных логов — для этого есть автоматическое отслеживание ошибок в журнале регистрации.
Откроем Журнал регистрации и настроим отбор по следующим параметрам:
Фоновое выполнение задач (или поиск по ключевому слову в описании события).Внимательно изучим детальные записи об ошибках. Чаще всего здесь можно обнаружить падение транзакции на определенном обработчике (например, при попытке записи визы согласования РаботаСВизамиСогласования.Записать или проверке прав рабочих групп РаботаСРабочимиГруппами). Если ошибка вызвана правами доступа, то выполнение блокируется из-за того, что регламентное задание пытается завершить задачу от лица пользователя, у которого в данный момент урезаны права или установлена пометка удаления.
Если зависших задач относительно немного (например, несколько исторических процессов), самый быстрый способ вернуть управление пользователям — очистить очередь блокировки напрямую.
Выполним следующие действия по шагам:
Задачи для выполнения (в ДО 3.0 ищем справочник Очередь заданий) — быстро очистить зависшие записи поможет обработка очистки и редактирования регистров сведений 1С.Если в вашей системе регулярно происходят конфликты блокировок или пользователи жалуются на постоянное зависание кнопок, мы можем временно или на постоянной основе отключить асинхронный режим обработки. Это заставит систему выполнять все алгоритмы записи и проведения задач синхронно, непосредственно в момент нажатия кнопки пользователем.
Для этого выполним настройку в интерфейсе:
Использовать фоновый старт процессовИспользовать фоновое выполнение задачПосле отключения этих опций система перестанет использовать регистр ЗадачиДляВыполнения, и зависания очереди прекратятся. Однако учитывайте, что при высокой нагрузке (большом количестве одновременно работающих пользователей) это может привести к кратковременному замедлению интерфейса при записи документов.
Очень распространенная техническая проблема возникает при переходе на новые релизы конфигурации (например, при обновлении с редакции 1.2/2.0 на 2.1 или при работе с базами, которые ранее участвовали в распределенном обмене РИБ).
Суть проблемы заключается в том, что регламентный обработчик задач жестко сверяет узел обмена бизнес-процесса с предопределенным элементом текущего узла (ЭтотУзел). Если после обновления или переноса данных идентификатор узла обмена у существующих бизнес-процессов заполнился некорректно (например, стал равен битому GUID или заполнился нулями 0000-0000...), регламентное задание просто игнорирует такие процессы, и задачи зависают в очереди навсегда — устранить подобные ошибки в регистрах поможет обработка удаления битых ссылок в регистрах 1С.
Для исправления этой ситуации мы можем использовать два программных метода.
Рассмотрим код внешней обработки или расширения, которая временно подменяет стандартную выборку задач регламентного задания, игнорируя жесткую привязку к узлам обмена, и принудительно проталкивает все зависшие задачи:
&НаСервере
Процедура ВыполнитьЗависшиеЗадачиПринудительно() Экспорт
УстановитьПривилегированныйРежим(Истина);
ЭтотУзелОбмена = РаботаСБизнесПроцессами.ЭтотУзелОбменаДляОбработкиПроцессов;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗадачиДляВыполнения.Задача КАК Задача,
| ЗадачиДляВыполнения.Параметры КАК Параметры,
| ЗадачаИсполнителя.Исполнитель КАК Исполнитель,
| ЗадачаИсполнителя.Выполнена КАК Выполнена,
| ЗадачиДляВыполнения.КоличествоПопытокОбработки КАК КоличествоПопытокОбработки,
| ДанныеБизнесПроцессов.УзелОбмена КАК УзелОбмена
|ИЗ
| РегистрСведений.ЗадачиДляВыполнения КАК ЗадачиДляВыполнения
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Задача.ЗадачаИсполнителя КАК ЗадачаИсполнителя
| ПО ЗадачиДляВыполнения.Задача = ЗадачаИсполнителя.Ссылка
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДанныеБизнесПроцессов КАК ДанныеБизнесПроцессов
| ПО ЗадачаИсполнителя.БизнесПроцесс = ДанныеБизнесПроцессов.БизнесПроцесс
|ГДЕ
| ЗадачиДляВыполнения.СостояниеВыполнения = ЗНАЧЕНИЕ(Перечисление.СостоянияЗадачДляВыполнения.ГоватаКВыполнению)
| И ЗадачиДляВыполнения.КоличествоПопытокОбработки < 5";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
НачатьТранзакцию();
Попытка
ЗаблокироватьДанныеДляРедактирования(Выборка.Задача);
ЗадачаОбъект = Выборка.Задача.ПолучитьОбъект();
Если ЗадачаОбъект <> Неопределено И НЕ ЗадачаОбъект.Выполнена Тогда
лПараметры = Выборка.Параметры.Получить();
Если ТипЗнч(лПараметры) <> Тип("Структура") Тогда
лПараметры = Новый Структура;
КонецЕсли;
// Подменяем узел обмена на актуальный "ЭтотУзел" в бизнес-процессе
ПроцессОбъект = ЗадачаОбъект.БизнесПроцесс.ПолучитьОбъект();
ПроцессОбъект.ОбменДанными.Загрузка = Истина;
лУзелОбменаБП = ПроцессОбъект.УзелОбмена;
ПроцессОбъект.УзелОбмена = ЭтотУзелОбмена;
ПроцессОбъект.Записать();
// Выполняем задачу
ВыполнениеЗадачСервер.ВыполнитьЗадачуСПараметрами(ЗадачаОбъект, лПараметры);
// Возвращаем исходный узел обмена, чтобы не нарушать логику РИБ
ПроцессОбъект = ЗадачаОбъект.БизнесПроцесс.ПолучитьОбъект();
ПроцессОбъект.ОбменДанными.Загрузка = Истина;
ПроцессОбъект.УзелОбмена = лУзелОбменаБП;
ПроцессОбъект.Записать();
ПроцессОбъект.ОбменДанными.Загрузка = Ложь;
// Проверяем права участников процесса
АвторПроцесса = РаботаСБизнесПроцессами.АвторПроцессаЗадачи(ПроцессОбъект);
МультипредметностьКОРП.ПроверитьПраваУчастниковПроцессаИОтправитьУведомления(ПроцессОбъект, АвторПроцесса);
КонецЕсли;
РазблокироватьДанныеДляРедактирования(Выборка.Задача);
ЗафиксироватьТранзакцию();
Исключение
ИнформацияОбОшибке = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("ФоновоеВыполнениеЗадачПринудительно",
УровеньЖурналаРегистрации.Ошибка, , , ПодробноеПредставлениеОшибки(ИнформацияОбОшибке));
ОтменитьТранзакцию();
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Если в вашей базе накопилось множество процессов с неверно заполненными идентификаторами узлов обмена, правильнее будет исправить их один раз централизованно. Напишем и запустим обработку, которая найдет все записи с некорректным узлом обмена и перезапишет их значением по умолчанию:
&НаСервере
Процедура ИсправитьУзлыОбменаВБизнесПроцессах() Экспорт
УстановитьПривилегированныйРежим(Истина);
ЭтотУзелОбмена = РаботаСБизнесПроцессами.ЭтотУзелОбменаДляОбработкиПроцессов;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДанныеБизнесПроцессов.БизнесПроцесс КАК БизнесПроцесс,
| ДанныеБизнесПроцессов.УзелОбмена КАК УзелОбмена
|ИЗ
| РегистрСведений.ДанныеБизнесПроцессов КАК ДанныеБизнесПроцессов
|ГДЕ
| НЕ ДанныеБизнесПроцессов.УзелОбмена = &УзелОбмена";
Запрос.УстановитьПараметр("УзелОбмена", ЭтотУзелОбмена);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Сообщить("Найдено процессов для исправления: " + Выборка.Количество());
Пока Выборка.Следующий() Цикл
БП = Выборка.БизнесПроцесс.ПолучитьОбъект();
Если БП <> Неопределено Тогда
// Записываем БЕЗ ОбменДанными.Загрузка = Истина,
// чтобы система корректно обновила связанные подчиненные регистры сведений!
БП.УзелОбмена = ЭтотУзелОбмена;
Попытка
БП.Записать();
Исключение
Сообщить("Ошибка записи процесса " + БП.Ссылка + ": " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Сообщить("Корректировка узлов обмена завершена успешно.");
КонецПроцедуры
Еще одна скрытая причина, о которой редко пишут в официальной документации — пустое состояние процессов после перехода со старых редакций. В некоторых версиях ДО 2.1 в коде регламентных заданий присутствует фильтр, обрабатывающий только те процессы, у которых реквизит Состояние равен значению Активен.
Если в базе данных по какой-то причине это поле оказалось незаполненным, такие задачи также будут вечно ожидать обработки. Решается эта проблема написанием аналогичной групповой обработки, которая находит все активные (незавершенные) бизнес-процессы в регистре сведений ДанныеБизнесПроцессов с пустым состоянием и программно устанавливает значение Перечисление.СостоянияБизнесПроцессов.Активен.
Чтобы минимизировать риски повторного возникновения подобных проблем в будущем, рекомендуем придерживаться следующих правил:
Пользователи, убедитесь, что на нем не висят незавершенные задачи в очереди фонового выполнения.Применяя данные подходы, вы сможете оперативно восстановить работоспособность бизнес-процессов в компании и обеспечить стабильную и бесперебойную работу пользователей в системе «1С:Документооборот».