При интеграции 1С с интернет-магазинами часто возникает задача оперативного обновления данных. Когда количество товаров исчисляется десятками тысяч, а склады и типы цен исчисляются десятками, стандартные методы выгрузки «всего подряд» перестают работать. Обновление каждые 5 минут требует от системы ювелирной точности: нужно передавать только то, что изменилось, при этом не блокируя работу пользователей и не создавая избыточную нагрузку на сервер. В этой статье мы разберем, как построить эффективную систему дельта-выгрузки, используя современные механизмы платформы 1С.
Традиционно разработчики рассматривают два пути: использование Планов обмена или ручное сравнение остатков. Однако в условиях высокой интенсивности записей (большие документы перемещения, массовое обновление прайс-листов) оба метода имеют недостатки. Ручное сравнение запросом требует хранения «слепка» данных на момент предыдущей выгрузки, что удваивает объем хранимой информации. Стандартные планы обмена, в свою очередь, при регистрации изменений регистров накопления часто фиксируют только документ-регистратор. Это вынуждает систему при обмене перебирать все строки документа, даже если изменился остаток только по одной позиции, что создает лишнюю нагрузку.
Рассмотрим, как оптимизировать эти процессы, перейдя от модели «синхронизируем всё по расписанию» к модели «синхронизируем асинхронно только измененное».
Один из самых надежных способов — создание собственной «очереди задач». Вместо того чтобы пытаться выгрузить данные в момент проведения документа, мы лишь фиксируем факт изменения объекта. Это позволяет минимизировать время транзакции и избежать блокировок веб-сервиса.
Алгоритм реализации:
ОчередьВыгрузкиНаСайт с измерениями Номенклатура, Склад (если нужно) и ресурсом ДатаИзменения.ПриЗаписи для Регистров Накопления (остатки) и Регистров Сведений (цены).Проанализируем пример кода для подписки на запись набора записей регистра остатков:
Процедура ПриЗаписиРегистраОстатков(Источник, Отказ, Замещение) Экспорт
// Источник — это НаборЗаписей регистра накопления
ТаблицаИзменений = Источник.ВыгрузитьКолонку("Номенклатура");
// Удаляем дубли, чтобы не писать лишнего в очередь
ТаблицаИзменений.Свернуть("Номенклатура");
Для Каждого Стр Из ТаблицаИзменений Цикл
МенеджерЗаписи = РегистрыСведений.ОчередьВыгрузкиНаСайт.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Номенклатура = Стр.Номенклатура;
МенеджерЗаписи.ДатаИзменения = ТекущаяДатаСеанса();
МенеджерЗаписи.Записать();
КонецЦикла;
КонецПроцедуры
Такой подход гарантирует, что даже при отмене проведения документа или частичном изменении табличной части, в очередь попадут именно те ссылки, которые затронуты движениями. Фоновое задание, запускаемое каждые 5 минут, будет считывать записи из этого регистра, формировать JSON и очищать отработанные строки.
Если вы всё же решили использовать Планы обмена, важно обойти проблему регистрации только «Регистратора». Чтобы система знала конкретные товары, которые изменились, необходимо в той же подписке на событие регистрировать изменения программно для каждого товара.
Выясним, как это сделать правильно:
// Вместо автоматической регистрации используем программную
ПланыОбмена.ЗарегистрироватьИзменения(УзелСайта, МассивИзмененныхТоваров);
При этом при выгрузке данных следует использовать выборку порциями и метод ВыбратьИзменения(). Чтобы не блокировать таблицу изменений при интенсивной работе, рекомендуется использовать «грязное чтение» в запросах к виртуальным таблицам остатков, если бизнес-логика допускает небольшую погрешность в моменте.
При работе с 20 000 позиций формирование одной огромной структуры Соответствие или Структура для последующей сериализации в JSON может привести к перерасходу оперативной памяти и падению рабочего процесса 1С. Разберем, как использовать объект ЗаписьJSON для потоковой записи данных.
Рассмотрим правильный подход к генерации файла:
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл(ПутьКФайлу, "UTF-8");
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("items");
ЗаписьJSON.ЗаписатьНачалоМассива();
Пока ВыборкаДанных.Следующий() Цикл
// Записываем каждый товар отдельно, не загружая всё в память
СтруктураТовара = Новый Структура("id, price, stock",
ВыборкаДанных.Код,
ВыборкаДанных.Цена,
ВыборкаДанных.Остаток);
ЗаписатьДанныеJSON(ЗаписьJSON, СтруктураТовара);
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецМассива();
ЗаписьJSON.ЗаписатьКонецОбъекта();
ЗаписьJSON.Закрыть();
Использование метода ЗаписатьДанныеJSON в цикле позволяет системе эффективно сбрасывать данные в поток, что критически важно для частого обмена.
Для конфигураций на платформе 8.3 существует еще один изящный способ отслеживания изменений без использования планов обмена — поле DataVersion. Каждая запись в базе данных имеет скрытую системную версию. Вместо сложной логики сравнения, мы можем сохранять «номер последней выгруженной версии».
Проанализируем преимущества:
Чтобы еще больше оптимизировать обмен, воспользуемся советами опытных разработчиков:
Важный нюанс с отменой проведения: При отмене документа перемещения остатки товаров обнуляются или уменьшаются. Чтобы сайт об этом узнал, в вашей очереди (или плане обмена) обязательно должна фиксироваться ссылка на товар. Даже если текущие остатки по нему стали нулевыми, он должен попасть в выборку выгрузки, чтобы JSON содержал актуальное значение "stock": 0.
Подводя итог, можно сказать, что для системы с 20 000 товаров оптимальным выбором будет сочетание промежуточного Регистра Сведений (очереди) и потоковой записи JSON в фоновом задании. Это обеспечит максимальную отзывчивость системы для пользователей и гарантированную доставку изменений на сайт.