Предупреждение
Ниже речь не про блокировку регламентных заданий в консоли администрирования информационной базы, а про прикладной механизм блокировки, работающий в информационной базе на конфигурации, созданной с использованием БСП.
При начале выполнения регламентного задания
Все мы уже привыкли к тому, что существует стандарт 540 https://its.1c.ru/db/v8std/content/540/hdoc, в котором говорится о том, что в начале процедур обработчиков регламентных заданий необходимо помещать вызов:
ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(Метаданные.РегламентныеЗадания.<ИмяЗадания>);
Убедительно прошу прочитать стандарт внимательно, оказывается, не в абсолютно всех регламентах обязателен этот вызов. Но впрочем, продолжим.
Зачем же нужен этот вызов? Он делает очень много всего нужного.
Посмотрите схему, в ней я постарался отразить все, что там происходит:

Итак, последовательно проверяется:
-
Еще не завершено обновление программы
-
Это распределенная база, но сломана связь с главным узлом
-
Задание работает с внешними ресурсами, но запущено в копии базы
-
Задание зависит от функциональной опции, но запущено "вручную" без установки этой опции
-
Не установлены начальные региональные настройки
Если событие из списка выше наступает, возникает исключение. Действительно, зачем запускать регламент, если все еще идет обновление программы или программа сломана (условно)? Если же все хорошо, программа осуществляет следующую проверку и в конце концов передает управление самому регламентному заданию, чтобы оно выполнило полезную работу.
Самая полезная проверка тут конечно же - “Задание работает с внешними ресурсами, но запущено в копии базы”. Это супернужная вещь! До тех пор, пока в БСП не появился этот функционал, не раз сталкивался с историями о последствиях. Сколько баз было загублено невовремя снятой блокировкой регламентов и запущенным автоматически обменом копии с продом! Правда, лично не ломал так базы, но работал в организации, в которой это случилось, и принимал участие в реанимационных процедурах.
Как же работает эта проверка? И почему она вообще работает?
Блокировка работы с внешними ресурсами
Замечательный механизм. Если сделаем копию базы, при первом входе пользователь с правами администратора увидит такую картину.

Система получает значение константы ПараметрыБлокировкиРаботыСВнешнимиРесурсами. В этой константе в хранилище значений содержится структура, в которой есть поля РаботаСВнешнимиРесурсамиЗаблокирована, СтрокаСоединения, ИдентификаторБазы и другие. Если значение поля РаботаСВнешнимиРесурсамиЗаблокирована Истина или Неопределено, то в параметр сеанса РаботаСВнешнимиРесурсамиЗаблокирована записывается Истина, в противном случае система сравнивает изменился ли идентификатор базы или строка соединения. И если изменилась, записывает новые данные в константу и меняет параметр сеанса.
Таким образом сеанс всегда знает, работает ли он в заблокированной базе или нет.
А регламентное задание проверяет, работает ли оно с внешними ресурсами. Если работает и параметр сеанса РаботаСВнешнимиРесурсамиЗаблокирована = Истина, то задание отключается (зачем в принципе пытаться запускать его по расписанию, если нельзя) и завершается данный экземпляр регламентного задания.
Как же система узнает, работает ли регламент с внешними ресурсами? Тут тоже нет никакой магии, для каждого регламентного задания программно устанавливаются настройки. В методах ИнтеграцияПодсистемБСП.ПриОпределенииНастроекРегламентныхЗаданий и РегламентныеЗаданияПереопределяемый.ПриОпределенииНастроекРегламентныхЗаданий система заполняет строки таблицы настроек, заполняя колонки РегламентноеЗадание, ФункциональнаяОпция, РаботаетСВнешнимиРесурсами и другие. Тут нам интересна колонка РаботаетСВнешнимиРесурсами.
Например, регламент очистки сегментов описывается так
Настройка = Настройки.Добавить();
Настройка.РегламентноеЗадание = Метаданные.РегламентныеЗадания.ОчисткаСегментов;
Настройка.ФункциональнаяОпция = Метаданные.ФункциональныеОпции.ИспользоватьСегментыНоменклатуры;
А вот регламент рассылки отчетов так
Настройка = Настройки.Добавить();
Настройка.РегламентноеЗадание = Метаданные.РегламентныеЗадания.РассылкаОтчетов;
Настройка.РаботаетСВнешнимиРесурсами = Истина;
Видно, что рассылка отчетов работает с внешними ресурсами, а очистка сегментов - нет.
Соответственно, регламент обращается к этой таблице настроек и считывает свои настройки.
А в чем проблема?
Рассмотрим ситуацию из практики. У нас есть ЕРП версии 2.5, есть Документооборот версии 3, есть бесшовная интеграция между ними. Задача - запустить, доработать и в дальнейшем поддерживать эту интеграцию. Забудем маркетинговое наименование “бесшовная интеграция”, она очень даже шовная, и вспомним, что для синхронизации измененных объектов в ЕРП есть регламентное задание “Обмен данными с 1С:Документооборотом”. Дело условных пяти минут - делаем копию базы ЕРП, настраиваем интеграцию, снимаем блокировку регламентов в консоли администрирования. Но наш регламент, единожды запустившись и не сделав ничего полезного, сразу же становится выключенным. А в его состоянии - задание отменено.


С одной стороны - это же прекрасно! Умная система отключила регламент, не дала синхронизироваться нашей копии базы с документооборотом из продуктового контура! А с другой стороны - но мне же нужно запустить синхронизацию! Я хочу отладить ее! И кстати, я добросовестный программист, я прописал в адресе подключения документооборота адрес тестового сервера. Я ничего не сломаю! Но ЕРП не верит моим обещаниям и выключает регламент, даже если я вручную запускаю задание синхронизации. Ручной запуск регламента не помогает. Так как мы идем по той же самой схеме, те же самые проверки не дают ему запуститься.
И что, никак не побороть эту проблему?
Что делать, если регламент все-таки надо запустить?
Решений несколько и я встречал все в своей работе.
1. Указать базе, что это не копия, а просто база перемещена.
Железобетонно сработает. Правда все остальные регламенты, общающиеся с окружающим миром тоже заработают. И полетят рассылки отчетов из тестовой базы и прочие обмены с другими системами. Хорошо, но можно же отключить все “ненужные” регламенты. Да, можно. Отключают. Но иногда ошибаются, забывают и страдают. Главное преимущество данного метода в том, что нам ничего не надо дорабатывать.
2. Вынести код, который вызывается регламентным заданием, в свою обработку и вызывать его вручную
Такой вариант вполне работоспособен, почему бы и нет. Но для реализации вызова того же обмена с документооборотом нужно еще переносить некоторое число неэкспортных процедур. А если нам надо реализовать тестовый контур или контур предпрода, то там нужна работа регламента без упражнений с ручным запуском. Для другого нужного регламентного задания, проделываем ту же самую операцию.
3. Убрать расширением вызов злополучного метода - ПриНачалеВыполненияРегламентногоЗадания.
Например, так:
&ИзменениеИКонтроль("ВыполнитьОбменДанными")
Процедура Расш1_ВыполнитьОбменДанными()
#Удаление
ОбщегоНазначения.ПриНачалеВыполненияРегламентногоЗадания(
Метаданные.РегламентныеЗадания.ИнтеграцияС1СДокументооборотВыполнитьОбменДанными);
#КонецУдаления
Настройки = ИнтеграцияС1СДокументооборотБазоваяФункциональностьВызовСервера.ИспользоватьИнтеграцию();
Если Не Настройки.ИспользоватьИнтеграциюДО2 И Не Настройки.ИспользоватьИнтеграциюДО3 Тогда
УзелДокументооборота = ИнтеграцияС1СДокументооборотБазоваяФункциональностьПовтИсп.УзелДокументооборота();
ПланыОбмена.УдалитьРегистрациюИзменений(УзелДокументооборота);
Возврат;
КонецЕсли;
Хороший вариант. Можно сделать отдельное расширение только с этой доработкой и подключать его по необходимости. Для другого нужного регламента, делаем то же самое.
4. Добавить константу и включать ее в той базе, где нужно запускать регламентное задание.
При получении настроек регламентного задания (именно из-за настройки РаботаетСВнешнимиРесурсами задание блокируется) возвращать значение параметра РаботаетСВнешнимиРесурсами из этой константы.
Например:
Настройка.РаботаетСВнешнимиРесурсами = НЕ Константы.РазрешенаИнтеграцияС1СДОНаКопии.Получить();
Вариант еще лучше. Доработку можно включить в основной код разрабатываемой базы (в конфигурацию или расширение) и включать эту константу по необходимости. А для другого нужного регламентного задания заводим новую константу.
Это последнее решение мы и используем на текущем месте.
Но меня все равно беспокоило то, что для решения проблемы запуска регламента обмена в тестовом контуре, мы дорабатываем код конфигурации. Мы не решаем этой доработкой проблему бизнеса. Это код “мертвый”, он не используется в рабочем контуре, он работает только в тестовой среде!
Вот было бы что-то такое же простое, как вариант 1, но лишенное его недостатков. Что-то, чтобы можно было точечно разрешить выполнение произвольного регламентного задания...
5. Разрешить выполнение конкретного регламентного задания средствами БСП
Такие мысли заставили меня копать глубже, и изучая код БСП в очередной раз, я наткнулся на решение. Оно настолько простое, удивительно, что я не обращал внимание на него раньше.
В методе ПриНачалеВыполненияРегламентногоЗадания есть следующее:
ЗапускЗаданияРазрешен = ОбщегоНазначения.ХранилищеСистемныхНастроекЗагрузить("РегламентныеЗадания", РегламентноеЗадание.ИмяМетода);
Если ЗапускЗаданияРазрешен = Истина Тогда
Возврат;
КонецЕсли;
Вот и все. Если в хранилище системных настроек есть объект “РегламентныеЗадания” и в нем есть настройка с ключём, совпадающая с методом задания, блокировка регламента не происходит. Код, проверяющий настройку работы с внешними ресурсами просто не выполняется, мы выходим из процедуры проверки работы с внешними ресурсами. Обратите внимание на два момента проистекающие из использования метода БСП из ОбщегоНазначения:
- Метод регламентного задания записывается не “как он есть”, а обрезается до 128 символов. Причем, чтобы избежать дублирования, в конец имени метода добавляется хэш строки.
- Хранилище настроек читается для текущего пользователя.
Записать эту настройку - дело техники, воспользуемся близлежащим методом из БСП:
ОбщегоНазначения.ХранилищеСистемныхНастроекСохранить(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения)
ОписаниеНастроек, ИмяПользователя, ОбновитьПовторноИспользуемыеЗначения - здесь необязательные параметры. Но нам передавать имя пользователя обязательно, так как иначе система воспримет команду как запись настройки для текущего пользователя, то есть того пользователя, под которым мы вызываем этот метод.
Помните, в начале статьи в схеме я обозначил регламентное задание значком человечка? Этот человечек - на самом деле Actor, термин из uml и draw.io, обозначающий действующего субъекта. Им может быть как человек, так и другая сущность, которая что-то делает. Регламент отлично подходит под это определение. А если еще вспомнить, что регламент - это действие запускаемое под определенным пользователем, то использование этого символа еще более оправданно. Ведь все прописывают запуск нужных регламентов под определенными служебными пользователями? Если к регламенту привязан пользователь, легко мониторить его в консоли администрирования и в журнале регистрации.
А если мы сделаем одного служебного пользователя и назначим его нескольким регламентам, все равно использование этого метода позволит нам запустить регламент, так как разрешение дается фактически на сочетание отдельных пользователя и регламента.
Обработка для чтения и записи настройки разрешения запуска заданий
Повторю ссылку, где ее можно найти.
Обработка работает в любой конфигурации с БСП не ниже 3.0. Подготовлена для добавления в состав "Дополнительных отчетов и обработок".
При ее запуске вы видите список всех регламентных заданий, зарегистрированных в системе. Это не замена стандартной обработки "Регламентные и фоновые задания", тут только включение и отключение настройки разрешения запуска заданий. В самой правой колонке выводится пользователь, привязанный к заданию, и включить или отключить настройку можно, только если пользователь определен.
В левой колонке "Изменить разрешение" находится команда изменения. Если разрешение уже дано, команда убирает разрешение, если регламент не разрешен, команда устанавливает разрешение.

Все просто. Как бонус, можно использовать эту обработку для быстрого просмотра методов, привязанных к регламентным заданиям.
А что дальше?
Я успешно применяю этот метод в своей работе. Если мы вернемся к примеру с интеграцией между ЕРП и Документооборотом, то теперь при восстановлении контура предпрода, нужно зайти в ЕРП в режиме предприятия, изменить адрес подключения документооборота и разрешить запуск регламентного задания с помощью обработки выше. Конечно, все эти действия можно и автоматизировать.
Как долго будет работать такая схема? Думаю, долго. История версий БСП 3.0 и 3.1 показывает, что эта проверка существовала с самого начала и не менялась. Нет оснований думать, что что то изменится.
Код изучал и применял для ЕРП с версией БСП 3.1.10.492
Обработка, которой посвящена данная статья, лежит также здесь: https://github.com/yuriybylinkin/ManageBlockingScheduledJobs
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.11.335, 3.1.10.645
Вступайте в нашу телеграмм-группу Инфостарт