При работе с распределенными информационными базами (РИБ) в 1С часто возникает необходимость выполнения определенных задач на каждом узле по расписанию. Например, это может быть выгрузка данных из каждого магазина в центральный офис или выполнение регламентных проверок, специфичных для каждого узла. Однако, при неправильной настройке, мы можем столкнуться с проблемой дублирования объектов, таких как внешние обработки, на главном узле. Давайте вместе разберем, как правильно организовать такой процесс, чтобы избежать типовых ошибок и достичь желаемого результата.
Прежде чем перейти к решению, давайте кратко вспомним, как работает распределенная информационная база. РИБ предназначена для совместной работы территориально удаленных подразделений. Она позволяет каждой базе функционировать автономно, а синхронизация данных происходит посредством обмена сообщениями. Структура РИБ обычно иерархическая: есть центральный (корневой) узел и один или несколько подчиненных (периферийных) узлов.
Ключевым моментом является то, что при обмене данными между узлами передаются не только измененные данные, но и изменения в метаданных конфигурации, а также различные дополнительные объекты, включая внешние отчеты и обработки. Понимание этого процесса поможет нам правильно настроить распространение нашей внешней обработки.
Основная проблема, описанная в исходной ситуации – это скапливание одинаковых обработок на главном узле. Это происходит, когда мы пытаемся регистрировать одну и ту же внешнюю обработку вручную на каждом подчиненном узле, а затем эти регистрации синхронизируются обратно в центральный узел, создавая дубликаты. Чтобы избежать этого, мы должны использовать стандартный механизм распространения.
ВыгрузкаДанныхУзла.epf).Что происходит дальше? Когда мы регистрируем внешнюю обработку таким образом в центральном узле, она становится частью информационной базы. При очередной синхронизации данных между центральным и подчиненными узлами эта регистрация обработки будет автоматически передана во все подчиненные узлы. Это гарантирует, что на каждом узле будет доступна одна и та же версия обработки, и при этом не возникнет никаких дубликатов.
Таким образом, мы распространяем саму внешнюю обработку и информацию о ее регистрации по всей распределенной базе корректно, используя штатные механизмы РИБ. Нам больше не нужно вручную копировать и регистрировать ее на каждом узле.
Теперь, когда наша внешняя обработка доступна на всех узлах, нам нужно обеспечить ее выполнение по расписанию. Здесь кроется важный нюанс: расписания регламентных заданий, как правило, не синхронизируются между узлами РИБ и не должны включаться в планы обмена. Это означает, что если мы создадим регламентное задание с расписанием в центральном узле, оно не будет автоматически создано и запущено на периферийных узлах.
Для выполнения внешней обработки по расписанию на каждом периферийном узле нам необходимо создать регламентное задание локально на каждом таком узле. Это позволяет каждому узлу запускать обработку независимо, используя свои локальные данные (например, "магазин по умолчанию в узле"), что является одним из наших требований.
ВыполнитьВыгрузкуДанных() Экспорт, то мы указываем именно ее. Система сама найдет эту функцию в списке доступных дополнительных обработок.Повторяем эти шаги для каждого подчиненного узла, на котором требуется выполнение нашей внешней обработки по расписанию. Таким образом, каждый узел будет иметь свое собственное регламентное задание, которое будет вызывать уже синхронизированную обработку.
Важным требованием было использование "магазина по умолчанию в узле". Внутри вашей внешней обработки вы сможете получить доступ к локальным данным текущего узла. Например, для 1С:Розница магазин по умолчанию часто хранится в константах.
Рассмотрим примерный код, который можно разместить в модуле объекта вашей внешней обработки:
// В модуле объекта внешней обработки (например, "ВыгрузкаДанныхУзла.epf")
// Данная функция будет вызываться регламентным заданием
Функция ВыполнитьВыгрузкуДанных() Экспорт
Попытка
// Получаем информацию о текущем узле РИБ.
// Это может быть полезно для логирования или специализированной обработки.
// Для Розницы чаще всего достаточно получить данные по магазину.
ТекущийУзелОбмена = ПланыОбмена.Полный.ЭтотУзел();
Сообщить("Выполняется выгрузка на узле: " + ТекущийУзелОбмена.Наименование);
// Получаем магазин по умолчанию для текущего узла.
// Для 1С:Розница это обычно константа "ОсновнойМагазин" или подобная.
МагазинПоУмолчанию = Константы.ОсновнойМагазин.Получить();
Если МагазинПоУмолчанию.Пустая() Тогда
ЗаписьЖурналаРегистрации(
"ВыгрузкаДанныхРИБ.Ошибка",
УровеньЖурналаРегистрации.Ошибка,
Метаданные.Константы.ОсновнойМагазин,
МагазинПоУмолчанию,
"Не установлен основной магазин для текущего узла. Выгрузка невозможна."
);
Возврат Ложь;
КонецЕсли;
Сообщить("Магазин по умолчанию для выгрузки: " + МагазинПоУмолчанию.Наименование);
// Здесь мы размещаем основную логику выгрузки данных.
// Например, запрос к данным, который фильтрует информацию по этому магазину.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ТоварыНаСкладахОстатки.Номенклатура,
| ТоварыНаСкладахОстатки.ХарактеристикаНоменклатуры,
| ТоварыНаСкладахОстатки.Склад,
| ТоварыНаСкладахОстатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
|ГДЕ
| ТоварыНаСкладахОстатки.Склад.Магазин = &Магазин";
Запрос.УстановитьПараметр("Магазин", МагазинПоУмолчанию);
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Если РезультатЗапроса.Количество() > 0 Тогда
// Дальнейшая логика по обработке/сохранению/отправке полученных данных.
// Например, сохранение в файл, отправка по FTP, запись в веб-сервис и т.д.
Сообщить("Успешно выгружено " + РезультатЗапроса.Количество() + " строк данных для магазина " + МагазинПоУмолчанию.Наименование);
ЗаписьЖурналаРегистрации(
"ВыгрузкаДанныхРИБ.Успех",
УровеньЖурналаРегистрации.Информация,
,
,
"Успешное выполнение выгрузки данных для магазина " + МагазинПоУмолчанию.Наименование + ". Выгружено строк: " + РезультатЗапроса.Количество()
);
Иначе
Сообщить("Нет данных для выгрузки по магазину " + МагазинПоУмолчанию.Наименование);
ЗаписьЖурналаРегистрации(
"ВыгрузкаДанныхРИБ.Инфо",
УровеньЖурналаРегистрации.Информация,
,
,
"Нет данных для выгрузки по магазину " + МагазинПоУмолчанию.Наименование
);
КонецЕсли;
Возврат Истина;
Исключение
ЗаписьЖурналаРегистрации(
"ВыгрузкаДанныхРИБ.Ошибка",
УровеньЖурналаРегистрации.Ошибка,
,
,
"Произошла ошибка при выполнении выгрузки данных: " + ОписаниеОшибки()
);
Возврат Ложь;
КонецПопытки;
КонецФункции
Этот код демонстрирует, как в теле вашей обработки можно получить специфичные для узла данные (в данном случае, "ОсновнойМагазин") и использовать их в логике. Функция ВыполнитьВыгрузкуДанных() должна быть экспортной, чтобы ее можно было вызвать из регламентного задания.
Для корректной работы регламентного задания, вызывающего внешнюю обработку, необходимо учесть несколько важных моментов:
Проблема "скапливания обработок с одним именем" на главном узле при синхронизации возникает, когда помимо данных и самой внешней обработки, обмену подвергаются и регистрации регламентных заданий или дополнительные обработки, созданные локально на периферийных узлах. Правильный подход, как мы выяснили, заключается в следующем:
Следуя этим рекомендациям, мы успешно настроим выполнение внешней обработки по расписанию на каждом узле РИБ 1С:Розница, избежим дублирования объектов в центральном узле и обеспечим корректную работу каждого узла с его специфическими локальными данными.