При разработке расширений для конфигураций на платформе «1С:Предприятие 8» программисты часто сталкиваются с жесткими ограничениями. Долгое время одним из самых неприятных ограничений была невозможность создавать собственные объекты метаданных типа РегламентныеЗадания непосредственно внутри расширения. Если логика приложения требует автоматического фонового выполнения кода по расписанию, разработчикам приходилось искать обходные пути.
В этой статье мы подробно разберем, как решить эту задачу. Мы рассмотрим как современные возможности платформы «1С:Предприятие», так и надежные «обходные» архитектурные методы, которые применимы на старых версиях платформы и конфигурациях, находящихся на совместимости.
Если ваша информационная база работает на платформе версии 8.3.23 или выше, и режим совместимости конфигурации установлен соответствующий, вам больше не нужно использовать сложные обходные пути. Фирма «1С» официально добавила поддержку регламентных заданий в расширениях.
Для реализации этого сценария выполните следующие шаги:
РегламентныеЗадания, нажмите кнопку «Добавить» и создайте новое собственное регламентное задание.Сервер и Вызов сервера (при необходимости).РегламентныеЗаданияМенеджер.Важное ограничение: Этот элегантный способ не сработает, если ваша основная конфигурация (например, ERP, ЗУП или УТ) все еще находится в режиме совместимости с версиями ниже 8.3.23. В таких случаях нам на помощь приходят классические альтернативные методы.
Если расширение планируется распространять массово («для сотен клиентов»), ручная установка внешних обработок силами пользователей не подходит. Лучшим решением будет упаковать логику регламентного задания во внешнюю обработку, поместить ее внутрь расширения как двоичный макет и программно регистрировать в справочнике ДополнительныеОтчетыИОбработки (Библиотека Стандартных Подсистем) при первом запуске расширения.
Давайте пошагово разберем, как реализовать этот отказоустойчивый механизм.
Создайте внешнюю обработку. В модуле объекта этой обработки обязательно должна присутствовать экспортная функция СведенияОВнешнейОбработке(), которая возвращает параметры регистрации для БСП, а также процедура-обработчик ВыполнитьКоманду().
Рассмотрим пример кода модуля объекта внешней обработки:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("3.0.3.109"); // Укажите актуальную версию БСП вашей базы
ПараметрыРегистрации.Наименование = "Регламентное выполнение задач из расширения";
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка;
ПараметрыРегистрации.Версия = "1.0.0.1";
ПараметрыРегистрации.БезопасныйРежим = Ложь; // Измените на Истина, если обработке не нужны привилегированные операции
ПараметрыРегистрации.Информация = "Регламентная обработка, запускаемая автоматически из расширения.";
// Добавление команды для выполнения по расписанию
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Запуск регламентного алгоритма расширения";
НоваяКоманда.Идентификатор = "ЗапуститьРегламентнуюПроцедуру";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.TypeКомандыВызовСерверногоМетода();
НоваяКоманда.ПоказыватьОповещение = Ложь;
Возврат ПараметрыРегистрации;
КонецФункции
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполненияКоманды) Экспорт
Если ИдентификаторКоманды = "ЗапуститьРегламентнуюПроцедуру" Тогда
ВыполнитьОсновнойАлгоритм();
КонецЕсли;
КонецПроцедуры
Процедура ВыполнитьОсновнойАлгоритм()
// Здесь располагается основной исполняемый код вашего регламентного задания.
// При необходимости можно вызвать экспортный метод общего модуля расширения:
// МойОбщийМодульРасширения.ВыполнитьРегламентнуюОперацию();
ЗаписьЖурналаРегистрации("РегламентноеЗаданиеРасширения",
УровеньЖурналаРегистрации.Информация, , ,
"Регламентное задание успешно запущено и выполнено программно!");
КонецПроцедуры
Сохраните созданную внешнюю обработку на диск в формате .epf. Перейдите в конфигуратор вашего расширения, найдите общие макеты, добавьте новый макет с типом Двоичные данные и загрузите в него сохраненный файл обработки. Назовите макет, например, РегламентнаяОбработкаДвоичныеДанные.
Теперь нам нужно написать алгоритм, который автоматически извлечет файл из двоичного макета и зарегистрирует его в справочнике БСП ДополнительныеОтчетыИОбработки с включенным расписанием.
Для этого мы можем использовать обработчик обновления информационной базы в расширении или переопределить процедуру при старте системы. Рассмотрим пример программной установки:
Процедура АвтоматическиЗарегистрироватьОбработку() Экспорт
ИмяОбработкиВБСП = "Регламентное выполнение задач из расширения";
СсылкаНаОбработку = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию(ИмяОбработкиВБСП);
// Проверяем, зарегистрирована ли уже обработка
Если ЗначениеЗаполнено(СсылкаНаОбработку) Тогда
// При необходимости здесь можно обновить версию обработки из макета
Возврат;
КонецЕсли;
// Получаем файл из двоичного макета расширения
ДвоичныеДанныеМаккета = ПолучитьОбщийМакет("РегламентнаяОбработкаДвоичныеДанные");
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("epf");
ДвоичныеДанныеМаккета.Записать(ИмяВременногоФайла);
// Создаем новый элемент справочника БСП программно
НовыйОбъект = Справочники.ДополнительныеОтчетыИОбработки.СоздатьЭлемент();
НовыйОбъект.Наименование = ИмяОбработкиВБСП;
НовыйОбъект.Вид = Перечисления.ВидыДополнительныхОтчетовИОбработок.ДополнительнаяОбработка;
НовыйОбъект.Публикация = Перечисления.ВариантыПубликацииДополнительныхОтчетовИОбработок.Используется;
НовыйОбъект.ХранилищеОбработки = Новый ХранилищеЗначения(Новый ДвоичныеДанные(ИмяВременногоФайла));
НовыйОбъект.ИмяФайла = "ScheduledTaskExtension.epf";
// Заполняем команды программно
НоваяСтрокаКоманды = НовыйОбъект.Команды.Добавить();
НоваяСтрокаКоманды.Идентификатор = "ЗапуститьРегламентнуюПроцедуру";
НоваяСтрокаКоманды.Представление = "Запуск регламентного алгоритма расширения";
НоваяСтрокаКоманды.ВариантЗапуска = Перечисления.СпособыВызоваДополнительныхОбработок.ВызовСерверногоМетода;
// Настраиваем использование регламентного задания внутри БСП
НовыйОбъект.ИспользоватьРегламентноеЗадание = Истина;
// Настраиваем расписание по умолчанию (например, каждый день в 1:00 ночи)
НовоеРасписание = Новый РасписаниеРегламентногоЗадания;
НовоеРасписание.ВремяНачала = '00010101010000'; // 01:00:00
// Сохраняем расписание в настройках БСП
НовыйОбъект.РегламентноеЗаданиеРасписание = Новый ХранилищеЗначения(НовоеРасписание);
Попытка
НовыйОбъект.Записать();
// Регистрируем регламентное задание в системных механизмах через БСП API
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("ОбъектДополнительногоОтчетаИЛиОбработки", НовыйОбъект.Ссылка);
// Вызываем серверный метод БСП для актуализации регламентных заданий
ДополнительныеОтчетыИОбработки.ОбновитьРегламентныеЗадания(ПараметрыРегистрации);
ЗаписьЖурналаРегистрации("РегламентноеЗаданиеРасширения",
УровеньЖурналаРегистрации.Информация, , ,
"Дополнительная обработка из расширения успешно зарегистрирована в БСП!");
Исключение
ЗаписьЖурналаРегистрации("РегламентноеЗаданиеРасширения",
УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка при автоматической регистрации обработки: " + ОписаниеОшибки());
КонецПопытки;
// Очищаем временный файл с диска сервера
УдалитьФайлы(ИмяВременногоФайла);
КонецПроцедуры
Этот подход полностью автоматизирует процесс развертывания решения. Клиенту достаточно просто установить один файл расширения, и вся необходимая инфраструктура регламентных заданий БСП развернется автоматически.
Если конфигурацию заказчика разрешено минимально редактировать (она снята с поддержки с сохранением возможности изменения), но критически важно не загромождать основную конфигурацию чужим функционалом для облегчения последующих обновлений, мы можем применить архитектуру «Моста».
Суть метода заключается в разделении ответственности:
ИмяПроекта_РегламентныеЗадания).Пример кода вызова метода расширения из общего модуля основной конфигурации:
Процедура ЗапуститьОбработчикИзРасширения() Экспорт
ИмяМодуляРасширения = "МойМодульИзРасширенияСервер";
Если ОбщегоНазначения.ЕстьОбщийМодуль(ИмяМодуляРасширения) Тогда
// Динамический вызов метода расширения через БСП или стандартный метод платформы
Выполнить(ИмяМодуляРасширения + ".ВыполнитьОсновнуюРегламентнуюРаботу();");
Иначе
ЗаписьЖурналаРегистрации("МостРегламентныхЗаданий",
УровеньЖурналаРегистрации.Предупреждение, , ,
"Попытка вызова регламентного задания, но расширение не установлено или отключено.");
КонецЕсли;
КонецПроцедуры
Этот метод гарантирует, что при обновлении основной конфигурации у вас никогда не возникнет конфликтов в коде, так как объект «Моста» содержит всего одну статичную строчку, не меняющуюся годами.
Если ваше решение разрабатывается для публикации в облачном сервисе по технологии 1С:Fresh, в нем реализован специализированный механизм управления задачами:
ВыполнитьКоманду().Мы проанализировали различные варианты создания регламентных заданий в расширениях. Для современных платформ (8.3.23+) лучшим выбором будет использование нативного встроенного механизма метаданных расширения. Для унаследованных систем идеальным решением является автоматическая программная регистрация внешней обработки из двоичного макета расширения, что гарантирует удобство дистрибуции и стабильную работу без снятия основной конфигурации с замка.