Разработка в расширениях конфигурации стала стандартом де-факто для кастомизации типовых решений «1С:Предприятия». Однако при реализации сложных бизнес-требований разработчики часто сталкиваются с необходимостью выполнять определенный код в фоновом режиме по заданному расписанию. Например, это может быть регулярная синхронизация данных с внешним сервисом, отправка уведомлений или регламентная очистка временных таблиц. Для настройки постоянного обмена между базами 1С без написания собственного кода расписания применяется программа регулярного автоматического обмена данными по расписанию.
В этой статье мы подробно разберем, как решить задачу запуска кода из расширения по расписанию. Мы проанализируем ситуацию с ограничениями платформы в разных версиях, рассмотрим штатные механизмы Библиотеки Стандартных Подсистем (БСП) и разберем альтернативные («обходные») варианты, которые могут пригодиться в устаревших конфигурациях.
Выясним причину, по которой данный вопрос вызывает так много споров в сообществе разработчиков. Исторически платформа «1С:Предприятие» имела жесткие ограничения на состав объектов метаданных, которые можно создавать в расширениях. Долгое время объект типа РегламентноеЗадание был недоступен для добавления непосредственно в расширение.
Важная веха развития платформы: полноценная поддержка создания собственных регламентных заданий в расширениях появилась только в версии платформы 8.3.23. Если ваша конфигурация работает на более старой версии платформы или использует режим совместимости ниже 8.3.23 (что до сих пор часто встречается в крупных корпоративных базах данных), добавить объект РегламентноеЗадание в расширение стандартным способом не получится — платформа выдаст ошибку совместимости.
Именно поэтому разработчикам приходится прибегать к альтернативным архитектурным решениям. Рассмотрим их подробнее по шагам, начиная от наиболее правильных («экологичных») и заканчивая обходными путями.
Если режим совместимости вашей основной конфигурации позволяет использовать возможности платформы версии 8.3.23 и выше, этот способ является самым простым и приоритетным. Нам не потребуется писать никаких дополнительных внешних обработок.
Выполним следующие шаги для настройки:
Общие найдем раздел РегламентныеЗадания и добавим новое регламентное задание._РегЗаданиеСинхронизации) и укажем имя метода, который должен вызываться. Обратите внимание, что метод должен располагаться в неглобальном общем модуле расширения с установленными свойствами Сервер и ВызовСервера.Посмотрим на пример кода серверного общего модуля расширения _ОбщийМодульФоновыеЗадачи, метод которого вызывается регламентным заданием:
Процедура ВыполнитьРегламентнуюСинхронизацию() Экспорт
// Записываем начало выполнения в журнал регистрации для контроля
ЗаписьЖурналаРегистрации(
"Расширение.Синхронизация",
УровеньЖурналаРегистрации.Информация,
,
,
"Запуск регламентной синхронизации из расширения..."
);
Попытка
// Здесь располагается основная бизнес-логика
ВыполнитьОбменДаннымиССервером();
Исключение
ЗаписьЖурналаРегистрации(
"Расширение.Синхронизация",
УровеньЖурналаРегистрации.Ошибка,
,
,
"Ошибка при выполнении синхронизации: " + ОписаниеОшибки()
);
КонецПопытки;
КонецПроцедуры
Этот способ идеален, так как он полностью контролируется платформой, отображается в стандартной консоли регламентных заданий и не требует внедрения лишних сущностей в базу данных. Для простого включения и отключения задач в базе можно воспользоваться внешней обработкой для управления регламентными заданиями на БСП.
Что делать, если режим совместимости конфигурации ниже 8.3.23? Наиболее надежным и архитектурно правильным решением в этом случае является интеграция расширения со справочником ДополнительныеОтчетыИОбработки, который входит в состав БСП и присутствует практически во всех типовых решениях (ERP, УТ, КА, БП, ЗУП).
Идея метода заключается в разделении логики: мы пишем всю сложную бизнес-логику в общем модуле расширения, а для ее регулярного запуска создаем простую внешнюю обработку, которая будет служить «пусковым крючком» (триггером). Эту внешнюю обработку мы регистрируем в справочнике дополнительных обработок информационной базы и настраиваем ее запуск по расписанию штатными средствами БСП.
Разберем этот процесс по шагам:
СведенияОВнешнейОбработке() и процедуру запуска команды.Проанализируем пример кода модуля объекта такой внешней обработки:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидДополнительногоОтчетаИлиОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Наименование = "Регламентный запуск задач из расширения";
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.БезопасныйРежим = Ложь; // Если требуется доступ к файлам или интернету
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Запустить фоновую задачу расширения";
НоваяКоманда.Идентификатор = "ЗапускЗадачиРасширения";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипЗапускаВызовСерверногоМетода();
НоваяКоманда.ПоказыватьОповещение = Ложь;
Возврат ПараметрыРегистрации;
КонецФункции
Процедура ВыполнитьКоманду(ИдентификаторКоманды, СопутствующиеПараметры) Экспорт
Если ИдентификаторКоманды = "ЗапускЗадачиРасширения" Тогда
// Обращаемся к общему модулю нашего расширения
Попытка
_ОбщийМодульФоновыеЗадачи.ВыполнитьРегламентнуюСинхронизацию();
Исключение
ЗаписьЖурналаРегистрации(
"ДополнительнаяОбработка.Ошибка",
УровеньЖурналаРегистрации.Ошибка,
,
,
"Не удалось вызвать метод расширения: " + ОписаниеОшибки()
);
ВызватьИсключение "Ошибка выполнения команды расширения: " + ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
КонецПроцедуры
После создания обработки выполняем следующие действия в режиме «1С:Предприятие»:
ЗапускДополнительныхОбработок с отбором по нашей обработке.Преимущества данного метода: полная безопасность, соответствие стандартам разработки 1С, корректная работа в клиент-серверном варианте и облачных сервисах (например, 1С:Fresh через механизм прохождения аудита).
Рассмотрим подробнее сценарий работы в облаке или в высоконагруженных системах, использующих модель разделения данных (SaaS). В составе БСП есть мощная подсистема ОчередьЗаданий. Начиная с определенных версий БСП, в ней реализована поддержка команд, поставляемых непосредственно внутри расширений.
Для интеграции с этим механизмом расширению не нужны внешние обработки. Вся настройка происходит на уровне кода расширения:
ДополнительныеОтчетыИОбработкиПереопределяемый).Этот способ является наиболее технологичным для распределенных облачных платформ, так как позволяет избежать хаотичного роста числа физических регламентных заданий в СУБД, группируя их выполнение в едином потоке очереди. В качестве альтернативного решения для запуска алгоритмов по гибким графикам можно использовать подсистему регулярных заданий для выполнения произвольного кода.
Проанализируем ситуацию, которая часто обсуждается на технических форумах: что делать, если нужно быстро «на коленке» запустить код по расписанию, база работает в файловом режиме или у вас нет прав на добавление внешних обработок в справочник БСП? Здесь разработчики прибегают к хитроумному приему — перехвату (или заимствованию) уже существующего регламентного задания из основной конфигурации.
Важное предупреждение: этот способ является недокументированным «костылем». Используйте его только в крайних случаях, когда другие варианты абсолютно невозможны, и вы полностью осознаете риски нарушения логики типового решения!
Суть метода заключается в следующем:
ПолучениеНовостей, ОбновлениеКлассификаторов, или специализированное пустое задание (если разработчики типового решения заложили его «на будущее»).&После или &Перед) подключаем наш собственный код к выполнению этого задания.Посмотрим на пример реализации такого перехвата для гипотетического задания получения новостей:
&Вместо("ПолучитьНовостиСервера")
Процедура _Демо_ПолучитьНовостиСервера()
// Сначала вызываем оригинальный метод, чтобы не нарушать работу системы
ПродолжитьВызов();
// Теперь выполняем наш собственный регламентный код
Попытка
_ОбщийМодульФоновыеЗадачи.ВыполнитьРегламентнуюСинхронизацию();
Исключение
// Обязательно перехватываем ошибки, чтобы сбой в нашем коде
// не привел к аварийному завершению работы стандартного механизма
ЗаписьЖурналаРегистрации(
"Расширение.ПерехватЗадания",
УровеньЖурналаРегистрации.Предупреждение,
,
,
"Ошибка выполнения нашего кода внутри типового задания: " + ОписаниеОшибки()
);
КонецПопытки;
КонецПроцедуры
Критический недостаток метода: нарушается базовый принцип разработки программного обеспечения — предсказуемость поведения системы. Если другой администратор или программист решит отключить «Получение новостей», он заблокирует и вашу критически важную синхронизацию данных, даже не подозревая об этом.
Иногда задачу запуска периодического кода можно решить вообще без использования расписания и регламентных заданий. Начиная с версии платформы 8.3.17, разработчикам доступен полноценный механизм создания собственных подписок на события в расширениях.
Если ваша задача состоит в том, чтобы реагировать на изменение данных (например, отправлять информацию о новом заказе клиента на внешний сайт), не нужно запускать регламентное задание каждую минуту для поиска измененных объектов. Достаточно создать подписку на событие ПриЗаписи или ПередЗаписью для нужного документа прямо в расширении.
Настроить подписку в расширении можно по следующей схеме:
ПодпискаНаСобытие.ДокументСсылка.ЗаказПокупателя), так и обобщенный тип (например, ДокументОбъект). Для доступа к обобщенному типу достаточно заимствовать хотя бы один документ соответствующего вида.ПриЗаписи).Пример кода обработчика подписки в расширении:
Процедура _ПодпискаПриЗаписиДокументаПриЗаписи(Источник, Отказ, Замещение) Экспорт
Если Отказ Тогда
Возврат;
КонецЕсли;
// Проверим, что это именно тот документ, который нас интересует
Если ТипЗнч(Источник) = Тип("ДокументОбъект.ЗаказПокупателя") Тогда
// Запускаем быструю асинхронную отправку или регистрируем изменения
РегистрацияИзмененийДляВыгрузки(Источник.Ссылка);
КонецЕсли;
КонецПроцедуры
Помните, что обработчики подписок из расширения выполняются платформой после выполнения основного кода модуля объекта конфигурации, но порядок выполнения между разными расширениями платформой не гарантируется.
Для того чтобы вам было проще сделать выбор архитектурного решения для своего проекта, сопоставим рассмотренные методы в сводной таблице:
| Метод | Минимальная версия платформы / БСП | Сложность реализации | Безопасность и стабильность | Рекомендуемая область применения |
|---|---|---|---|---|
| Штатное задание в расширении | Платформа 8.3.23 (без режима совместимости) | Низкая | Высокая | Новые проекты на актуальных версиях платформы 1С. |
| Внешняя обработка БСП | Любая версия БСП с подсистемой доп. обработок | Средняя | Высокая | Типовые конфигурации в режиме совместимости ниже 8.3.23. Универсальный промышленный стандарт. |
| Очередь заданий БСП | БСП с поддержкой команд расширений | Высокая | Высокая | Облачные решения (1C:Fresh), SaaS-архитектура, мультиарендные базы данных. |
| Перехват существующего задания | Любая | Низкая | Очень низкая | Экстренное исправление в условиях жестких ограничений, временные решения («костыли»). |
Таким образом, проанализировав все возможные варианты, мы рекомендуем ориентироваться на требования вашей ИТ-инфраструктуры. Для большинства коммерческих внедрений на сегодняшний день связка «бизнес-логика в расширении + вызов через дополнительную обработку БСП» остается самым надежным, безопасным и простым в поддержке решением, гарантирующим стабильную работу системы при любых последующих обновлениях типовой конфигурации.