В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью автоматизировать выполнение задач. Один из способов — программное создание объектов типа РегламентноеЗадание. Однако нередко возникает ситуация: код написан правильно, задание создается, но планировщик его игнорирует до тех пор, пока пользователь не зайдет в консоль и не пересохранит его вручную. В этой статье мы подробно разберем, почему это происходит и как выстроить надежную архитектуру фонового выполнения задач.
Рассмотрим ситуацию, когда разработчик пытается запустить процесс от имени конкретного пользователя, создавая регламентное задание «на лету». Типичный код создания выглядит так:
мЗадание = РегламентныеЗадания.СоздатьРегламентноеЗадание("ПроверкаРазделенияПрав");
мЗадание.Использование = Истина;
мЗадание.Наименование = "Сессия проверки разделения прав для " + мИмяПользователя;
мЗадание.Ключ = мИмяПользователя;
мЗадание.ИмяПользователя = мИмяПользователя;
мЗадание.Записать();
На первый взгляд, все параметры заданы: Использование установлено в Истина, указано имя пользователя и метаданные. Но задание не стартует. Выясним основные технические причины такого поведения.
Проанализируем работу свойства Ключ. В системе 1С этот параметр предназначен для предотвращения одновременного запуска нескольких экземпляров одного и того же задания. Если вы программно создаете задание, выполняете его, удаляете, а затем сразу создаете новое с тем же самым ключом — планировщик может считать, что задание с таким идентификатором уже находится в очереди или недавно завершилось. Информация в оперативной памяти менеджера заданий на сервере обновляется не мгновенно, что создает эффект «зависшего кэша».
Важный вывод: Постоянное удаление и пересоздание регламентных заданий — это плохая практика. Система не успевает корректно обновлять внутренние таблицы планировщика.
Разберем, как планировщик 1С опрашивает базу данных. Сервер приложений обращается к списку регламентных заданий не каждую миллисекунду, а с определенным интервалом (обычно от 15 до 60 секунд). Если мы создаем однократное задание, расписание которого «тянется» из метаданных и предполагает немедленный запуск, время старта может формально «пройти» до того, как планировщик увидит новую запись в таблице. В итоге задание помечается как пропущенное.
Для стабильного запуска программных заданий рекомендуется устанавливать время начала хотя бы на 1-2 минуты вперед относительно текущего времени сервера:
НовоеРасписание = Новый РасписаниеРегламентногоЗадания;
НовоеРасписание.ДатаНачала = ТекущаяДата() + 60; // Старт через минуту
мЗадание.Расписание = НовоеРасписание;
Если ваша конфигурация работает в режиме разделения данных (например, в облаке), необходимо учитывать свойство РазделениеДанных. Если задание создается в сеансе с активными разделителями, а в метаданных оно помечено как общее, планировщик не поймет, к какой области данных оно относится. В некоторых случаях помогает явная очистка разделителей:
мЗадание.РазделениеДанных.Очистить();
Рассмотрим более надежный подход, к которому приходят опытные разработчики. Вместо того чтобы плодить временные регламентные задания, которые замусоривают систему и вызывают конфликты кэша, лучше использовать механизм очереди заданий или одно постоянное задание-диспетчер.
Как это работает по шагам:
ОбработкаОчередиСобытий).ОчередьЗаданий, куда будем записывать параметры: какого пользователя подставить, какой код выполнить и статус (Выполнено/Не выполнено).Такой подход позволяет избежать проблем с динамическим созданием объектов РегламентноеЗадание и гарантирует выполнение кода под нужными правами.
Если вам нужно запустить код прямо сейчас, а не по расписанию, проанализируем метод ФоновыеЗадания.Выполнить(). Это более «легкий» механизм. Однако помните, что фоновое задание по умолчанию наследует права текущего сеанса. Если вам критически важно выполнить код от имени другого пользователя (как в исходном вопросе), использование РегламентныеЗадания оправдано, но только в статичном виде.
Подведем итог нашему исследованию ситуации с программным запуском:
Записать() в коде должно сопровождаться полной инициализацией всех ключевых свойств объекта, включая расписание и имя пользователя.Следуя этим рекомендациям, вы сможете построить стабильную систему автоматизации в 1С, которая не будет требовать ручного вмешательства администратора.