Как застраховаться от отказа расширения конфигурации

27.10.26

Разработка - Механизмы типовых конфигураций

Отказ расширения конфигурации - это тихий сбой, который дорого стоит. Он иногда может случиться если обновить расширение динамически под нагрузкой. Как не испортить данные, когда расширение 1С отказало. Шаблонный подход - маркер «обработано расширением» для защиты от отказа расширения. Флаг автоматически ставится в расширении. Основная конфигурация проверяет его и если флаг не стоит, подозревает, что расширение отказало.

Пролог: тихий сбой, который дорого стоит

Представьте понедельник. Менеджеры оформляют заказы, логисты собирают отгрузки. Всё как обычно. Никто не знает, что ночью на сервере прошло динамическое обновление под нагрузкой, и платформа 1С отвергла расширение интеграции с сайтом. Оно больше не выполняется — но XML-обмен продолжает работать, ведь он часть основной конфигурации.

Сайт шлёт заказы. Типовая логика их принимает. Создаются партнёры, контрагенты, документы. Только вот валидация, транзакционность и корректный маппинг остались в отключённом расширении. В базу попадают дубли партнёров с пустым ИНН, заказы без вида цены и склада, контрагенты с неверными реквизитами.

Через два дня расширение снова активно. Всё работает. Но «кривые» партнёры уже «залипли» в новых заказах — менеджер видит двух «Интернет Решения ООО» и не понимает, какой правильный. Начинается ручная сверка: часы, дни, ошибки.

Знакомо? Это классическая проблема расширений в HighLoad-системах. И у неё есть красивое решение.


Часть 1. Почему это происходит

Что такое отказ расширения

Расширение конфигурации — мощный механизм. Но у него есть особенность: при динамическом обновлении под высокой вычислительной нагрузкой платформа может отвергнуть расширение. Это штатное поведение, не ошибка. Расширение просто перестаёт выполняться.

При этом:

  • Основная конфигурация продолжает работать.
  • Обмены, подписки, типовые механизмы — работают.
  • Код расширения — нет.

Если корректность обработки данных зависит от расширения (а в интеграциях это почти всегда так), отказ расширения означает: данные будут созданы, но некорректно.

Уточнение. В нашем окружении наблюдался сценарий, при котором после динамического обновления расширение переставало выполнять свой код. Поэтому мы рассматриваем этот отказ как сценарий, от которого должна защищать интеграция. Поведение платформы при динамическом обновлении под нагрузкой зависит от версии, режима обновления и инфраструктуры — универсальным свойством платформы его считать нельзя.

Два канала обмена — две разные судьбы

В нашем случае с сайтом есть два канала:

Канал Технология Обработчик Что происходит при отказе расширения
A YMQ (RabbitMQ) Расширение Обмен просто останавливается — данных нет
B XML (CommerceML) Типовая конфигурация Данные создаются некорректно

Канал A «умирает» вместе с расширением — это безопасно. Канал B продолжает работать, потому что типовая логика жива. И вот здесь начинается проблема.


Часть 2. Почему не стоит безусловно снимать отказ записи

Первое решение, которое приходит в голову, — добавить в расширение обработчик &После, который снимает отказ, если документ поступает из нужного обмена:

Если Источник.ОбменДанными.Загрузка Тогда
    Отказ = Ложь;
КонецЕсли;

Сам по себе этот подход не является ошибкой. В определённой архитектуре он может быть оправдан: например, если обработчик реализует согласованное правило, по которому конкретный обмен имеет право выполнять запись.

Проблема возникает, когда Отказ = Ложь используется как универсальное разрешение на запись без учёта причин, по которым отказ мог быть установлен ранее.

Здесь есть три момента.

1. Нужно учитывать взаимодействие обработчиков.

При работе с расширениями важно понимать, как устроена цепочка вызовов и в каком порядке выполняются обработчики в конкретной конфигурации. Нельзя автоматически считать, что присваивание Отказ = Ложь безопасно лишь потому, что оно находится в обработчике &После.

2. Снятие отказа может отменить чужое решение.

Если другой обработчик обнаружил нарушение бизнес-правил и установил Отказ = Истина, безусловное присваивание Отказ = Ложь способно разрешить запись, которую следовало заблокировать. Это особенно опасно, если один и тот же механизм записи используется несколькими интеграциями и сценариями работы.

3. Признак загрузки не доказывает корректность обработки.

Условие Источник.ОбменДанными.Загрузка указывает на режим загрузки данных, но само по себе не подтверждает, что конкретный заказ прошёл необходимую валидацию, получил правильные реквизиты и был обработан кодом расширения.

Поэтому для нашей задачи — защитить базу от некорректной загрузки при недоступности расширения — я предпочитаю другой механизм: основной конфигурации не нужно разрешать или запрещать запись на основании предположений о состоянии расширения. Она должна проверять явное условие, без которого запись недопустима. В рассматриваемом решении таким условием служит позитивный маркер обработки.

Вывод. Проблема не в самом присваивании Отказ = Ложь, а в его безусловном применении без согласованного контракта между обработчиками. Маркер — альтернативный способ организовать эту проверку, который лучше соответствует нашей задаче, если корректно обеспечены его жизненный цикл и область применения.

Часть 3. Как это уже решено для маркетплейсов

В нашей конфигурации есть рабочее решение для блокировки заказов маркетплейсов (WB, Ozon). Оно построено на позитивном признаке: «это чужое — блокировать».

Процедура ЗаказКлиента_ПередЗаписьюПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
    
    ЭтоМаркетплейс = Ложь;
    Причина = "";
    СсылкаКонтрагента = "";
    
    Если ЗначениеЗаполнено(Источник.Контрагент) Тогда
        
        // 1. По GUID контрагента (основная ветка)
        СсылкаКонтрагента = Строка(Источник.Контрагент.УникальныйИдентификатор());
        Если СсылкаКонтрагента = "8173d2b5-..." Тогда  // Wildberries
            ЭтоМаркетплейс = Истина;
            Причина = "контрагент Wildberries (по GUID)";
        ИначеЕсли СсылкаКонтрагента = "95a362ec-..." Тогда  // Ozon
            ЭтоМаркетплейс = Истина;
            Причина = "контрагент Ozon (по GUID)";
        КонецЕсли;
        
        // 2. По наименованию (запасная)
        // 3. По дополнительному реквизиту (последний резерв)
    КонецЕсли;
    
    Если ЭтоМаркетплейс Тогда
        Отказ = Истина;
        // ... логирование, сообщение ...
        Возврат;
    КонецЕсли;
КонецПроцедуры

Ключевая идея: в основной конфигурации стоит предохранитель, который блокирует заведомо нежелательные данные. Расширение не «разрешает» — оно просто не мешает предохранителю, потому что маркетплейсы и так не должны загружаться.

Но для сайта логика инвертируется: данные-то наши, просто они должны проходить через расширение. Значит, нужен позитивный маркер, который выставляет только расширение.


Часть 4. Решение: маркер «обработано расширением»

Идея

Есть реквизит СРС_МелкийОпт — базовый, существует в основной конфигурации. Расширение выставляет его в Истина в трёх точках:

  • ОбменССайтом:517-521 — новый заказ с сайта
  • ЗаказКлиента\ObjectModule:126-128 — заказ с маркируемым товаром
  • ЗаказКлиента\ФормаДокумента:312-314 — новый документ, открытый в форме

В типовом коде он не заполняется ни разу.

Важное ограничение: маркер доказывает обработку только для новых объектов

Для нового документа маркер изначально Ложь и выставляется только при успешной обработке. Здесь вывод «СРС_МелкийОпт = Ложь → код расширения не отработал» обоснован.

Но для существующего, скопированного или повторно загружаемого документа маркер может остаться Истина от предыдущей операции. Постоянный реквизит объекта — не доказательство обработки именно текущего запроса.

Перед тем как называть маркер гарантией, проверьте:
  1. Повторную загрузку существующего заказа — не остаётся ли СРС_МелкийОпт = Истина от прошлой операции.
  2. Копирование и ввод на основании — не переносится ли маркер.
  3. Все точки создания — выставляют ли они маркер.
Если хотя бы один из этих сценариев не закрыт — маркер работает как защита новых заказов, но не как универсальная гарантия.

Для полной гарантии можно использовать отдельный признак текущей операции — временный контекст обработки или идентификатор операции, проверяемый в рамках согласованного механизма интеграции. Но это уже более сложная архитектура.

Код предохранителя

Если НЕ Источник.СРС_МелкийОпт Тогда
    
    ТекстОтказа = СтрШаблон(
        "Заказ не записан: заказ не обработан расширением интеграции с сайтом (СРС_МелкийОпт = Ложь)."
        + Символы.ПС + "Номер: %1. Дата: %2. Контрагент: %3. Режим записи: %4.",
        СокрЛП(Источник.Номер),
        Строка(Источник.Дата),
        Строка(Источник.Контрагент),
        Строка(РежимЗаписи));
    
    Отказ = Истина;
    
    ЗаписьЖурналаРегистрации(
        "ЗаказКлиента.БлокировкаЗагрузкиССайта",
        УровеньЖурналаРегистрации.Ошибка,
        Источник.Ссылка,
        ,
        ТекстОтказа);
    
    ВызватьИсключение ТекстОтказа;
    
    Возврат;
    
КонецЕсли;

Отказ = Истина и исключение — разные задачи

В коде одновременно устанавливаются отказ и вызывается исключение. Это не два взаимозаменяемых способа гарантированно отменить одну и ту же операцию:

  • Отказ = Истина — сигнал механизму записи об отказе.
  • Исключение — механизм прерывания выполнения и передачи ошибки вызывающему коду.
  • Откат транзакции зависит от того, где открыта транзакция, как распространяется исключение и как его обрабатывает вызывающий код.

Поэтому тезис «исключение + Отказ = Истина гарантированно отменят всё» нужно заменить описанием проверенного сценария выполнения. Особенно важно проверить, что исключение действительно доходит до Попытка в типовом обмене и вызывает нужный откат, а не перехватывается промежуточным обработчиком.

Две разные задачи, которые нельзя смешивать

В решении смешаны два независимых требования:

  1. Не допустить запись некорректного заказа. Это решает маркер + предохранитель.
  2. Обеспечить атомарность обработки заказа, партнёра и контрагента. Это зависит от транзакционной архитектуры обмена.

Даже если заказ не записан, это ещё не доказывает, что партнёр и контрагент не успели сохраниться в другой транзакции или другом контексте выполнения. Этот вывод нужно подтверждать разбором конкретного пути загрузки.

Почему это лучше для нашей задачи

Критерий Снятие отказа через &После Позитивный маркер
Основная идея Разрешить запись при заданном условии Разрешить запись только при наличии подтверждения обработки
Основной риск Снять отказ, выставленный другим обработчиком Принять устаревший или ошибочно установленный маркер
Порядок обработчиков Требует анализа взаимодействия обработчиков Требует корректного места и момента проверки
Подтверждение обработки текущего заказа Зависит от реализации Надёжно только при гарантированном жизненном цикле маркера
Подходит для рассматриваемой задачи Возможно, при согласованном контракте Предпочтительно при соблюдении описанных условий

Часть 5. Производительность: почему порядок веток важен

В блоке маркетплейсов изначально было три проверки:

  1. По дополнительному реквизиту ID заказа на маркетплейсе (дорогой вызов УправлениеСвойствами.ЗначениеСвойства + Попытка)
  2. По GUID контрагента
  3. По наименованию контрагента

Проблема: самая надёжная ветка (GUID) стояла второй, а нерабочая (свойство) — первой. EventLog показал: в реальном потоке всегда срабатывает ветка по GUID, а ветка по свойству — никогда.

Исправление: порядок стал GUID → Наименование → Свойство.

Уточнение по выигрышу. Перестановка веток не уменьшает количество проверок автоматически для каждого сценария. Выигрыш возникает, когда условие в более ранней ветке выполняется и до последующих проверок выполнение не доходит. В нашем случае:
  • Обычный заказ (не маркетплейс, не сайт): выполняются все три проверки — количество не меняется, но меняется порядок: сначала быстрые строковые сравнения, потом дорогой вызов свойства.
  • Заказ Ozon/WB (по GUID): выполняется только ветка GUID — 1 проверка. Свойство и Наименование не проверяются.
Точный выигрыш: для маркетплейсов, определённых по GUID, — не выполняется дорогой вызов УправлениеСвойствами.ЗначениеСвойства и Попытка.

Плюс:

  • СсылкаКонтрагента инициализируется до условных блоков — нет риска обращения к неопределённой переменной.
  • Общий Если ЗначениеЗаполнено(Источник.Контрагент) вместо трёх повторных проверок.

Часть 6. Что важно проверить перед внедрением

Решение кажется простым, но есть нюансы, которые нужно проверить на своей базе.

1. Все ли пути создания объекта расширением выставляют маркер

Известные точки — это только то, что подтверждено. Но есть ли ещё? Копирование, ввод на основании, API-создание, альтернативные каналы загрузки — выставляют ли они маркер? Если хотя бы один путь не выставляет — объекты, созданные через него, будут заблокированы. Это критично.

2. Маркер — действительно базовый реквизит

Если он существует только в расширении — при отказе расширения его не будет, и обращение к нему вызовет ошибку. Это важно.

3. Типовой код не заполняет маркер

Подтверждено комментарием, но стоит перепроверить поиском по конфигурации.

4. После отката исходное сообщение не помечается как успешно обработанное

Иначе данные «потеряются» — исключение откатило транзакцию, но сообщение уже помечено как обработанное. Нужно проверить, как механизм обмена обрабатывает исключение.

5. Исключение не ломает другие обмены и сценарии

Общий флаг загрузки используется несколькими обменами. Если поднимать исключение без проверки специфического признака затронутого функционала — можно сломать другие обмены. Нужно проверить, что исключение поднимается только внутри нужного контекста.

Часть 7. Универсальный паттерн: «предохранитель + позитивный маркер»

Это решение можно обобщить на любую интеграцию, где корректность зависит от расширения.

Паттерн

  1. В основной конфигурации — предохранитель, который блокирует запись, если нет позитивного маркера от расширения.
  2. В расширении — маркер выставляется только в точках, где расширение гарантированно обработало данные.
  3. Маркер — базовый реквизит (существует без расширения), чтобы не было ошибки при отказе.
  4. Маркер никогда не сбрасывается в Ложь — только выставляется в Истина.
  5. Исключение для отката транзакции — только внутри специфического обмена.

Сравнение с «разрешителем» через &После

Критерий Снятие отказа через &После Позитивный маркер
Основная идея Разрешить запись при заданном условии Разрешить запись только при наличии подтверждения обработки
Основной риск Снять отказ, выставленный другим обработчиком Принять устаревший или ошибочно установленный маркер
Порядок обработчиков Требует анализа взаимодействия обработчиков Требует корректного места и момента проверки
Подтверждение обработки текущего заказа Зависит от реализации Надёжно только при гарантированном жизненном цикле маркера
Подходит для рассматриваемой задачи Возможно, при согласованном контракте Предпочтительно при соблюдении описанных условий

Эпилог: что это даёт бизнесу

Для сценариев, которые действительно проверены тестами:

  1. Предотвращает создание «кривых» партнёров при отказе расширения — при соблюдении условий применимости маркера.
  2. Снижает неопределённость — менеджер видит понятную ошибку в журнале, а не выбирает между двумя «Интернет Решения ООО».
  3. Сокращает напрасный труд — не нужно чистить базу после каждой аварии.
  4. Диагностируемость — в журнале регистрации видно, какой заказ заблокирован и почему.
  5. Позволяет организовать безопасный повтор — если настроить сохранение XML, заблокированные заказы можно переобработать после восстановления расширения.
Гарантии атомарности (откат партнёра и контрагента вместе с заказом) и безопасного повтора требуют отдельной проверки для конкретного пути загрузки. В статье они описаны как архитектурные предположения, а не как подтверждённые результаты.

Чек-лист для внедрения

  • VМаркер обработки — базовый реквизит (существует без расширения).
  • VТиповой код не заполняет маркер — иначе он не доказывает факт обработки расширением.
  • VВсе пути создания объекта расширением выставляют маркер.
  • VВсе альтернативные каналы (если они есть) выставляют маркер.
  • VМаркер не остаётся от прошлой операции — проверены сценарии повторной записи, копирования, ввода на основании.
  • VИсключение поднимается только внутри затронутого функционала — по специфическому признаку, а не по общему флагу загрузки.
  • VПосле отката исходное сообщение не помечается как успешно обработанное — иначе данные «потеряются» при повторе.
  • VПроверено на тестовой базе: расширение активно → обработка корректна.
  • VПроверено: расширение отключено → обработка блокируется.
  • VПроверено: ручное создание → не блокируется (или блокируется — по решению).
  • VПроверено: другие обмены и сценарии не ломаются.

Итоговый совет

Если обработка данных зависит от расширения, основной конфигурации нужен независимый механизм проверки того, что необходимые условия обработки выполнены. В нашей интеграции эту задачу решает позитивный маркер; его корректность зависит от:

  • жизненного цикла маркера (только новые объекты или все сценарии);
  • области применения проверки (только заказы или связанные объекты);
  • транзакционной модели обмена (где открыта транзакция, как распространяется исключение).

Это не спор с альтернативным решением через &После, а выбор подхода, который лучше соответствует конкретной архитектуре — при условии, что ограничения маркера проверены и закрыты.

Статья основана на реальном проекте интеграции 1С:КА 2.5 с сайтом через XML/CommerceML и YMQ. Решение прошло аудит, тестирование на рабочей базе и внедрено в продуктив.

 

Вступайте в нашу телеграмм-группу Инфостарт

1С расширение конфигурации HighLoad CommerceML XML-обмен отказ расширения транзакция позитивный маркер предохранитель интеграция с сайтом заказы клиентов маркетплейсы.

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Инструментарий разработчика Механизмы типовых конфигураций Разработчик 1С 8.5 1С:Управление нашей фирмой 3.0 Абонемент ($m)

Кто ссылается на этот справочник, на что ссылается документ и какие регистры он двигает — обработка показывает это схемой прямо в базе. Выбранный объект — в центре, слева — кто ссылается на него, справа — на что ссылается он, под схемой — через какой реквизит; щелчок по соседу делает центром его. Много соседей — группы по видам, связи через составные типы — пунктиром и отключаются флажком. Для документации схему можно взять текстом PlantUML или сохранить файлом HTML вместе с таблицей связей. В статье я разбираю код: связи по типам реквизитов, движениям и владельцам, временное хранилище формы, схему в поле HTML и щелчок по узлу.

2 стартмани

30.09.2026    879    18    Petr_32    2    

6

Механизмы типовых конфигураций Разработчик 1С:Предприятие 8 Абонемент ($m)

Использование переопределяемых процедур в 1С на управляемых формах.

1 стартмани

01.09.2026    4289    waider    3    

15

Механизмы типовых конфигураций Разработчик 1С:Предприятие 8 1С:Управление торговлей 11 Россия Бесплатно (free)

С 1 сентября компании с выручкой от 120 миллионов обязаны принимать цифровой рубль, за отказ — штраф до 50 тысяч за каждый случай. Я снял выгрузку с актуального релиза «Управления торговлей» и пошёл смотреть, где это включается. Оказалось, что казначейский контур в типовой сделан подробно, а кассового нет вообще — и это не забывчивость, а решение, записанное в конфигурации прямым текстом.

31.08.2026    2411    G_100802897175107255412    6    

5

Инструментарий разработчика БСП (Библиотека стандартных подсистем) Механизмы типовых конфигураций Разработчик 1С 8.3 1С:ERP Управление предприятием 2 Абонемент ($m)

Данное расширение — это механизм, сделанный при помощи двух модулей из БСП (3.1.11.415), который позволяет динамически добавлять команды (кнопки и не только при желании) на формы управляемого приложения без изменения конфигурации. На примере данного механизма удобно рассмотреть некоторые возможности для расширения функционала объектов, которые подключены к механизму библиотеки стандартных подсистем.

1 стартмани

20.03.2026    5362    InFlach    0    

6

Механизмы типовых конфигураций Разработчик Стажер 1С 8.3 1С:Зарплата и Управление Персоналом 3.x Бесплатно (free)

Интервальные регистры в 1С:ЗУП 3.1 заменяют тяжелые срезы последних, ускоряя отчеты по кадровым данным через интервалы ДатаНачала–ДатаОкончания. Разбираем отличия, примеры кода, плюсы и способы синхронизации.

12.03.2026    7202    AlexeyPROSTO_1C    5    

21

Механизмы типовых конфигураций Разработчик Стажер 1С 8.3 1С:Зарплата и Управление Персоналом 3.x Бесплатно (free)

Как в ЗУП работает механизм расстановки времени в регистрах сведений с помощью подписки на события?Рассматривается логика сдвигов для разных типов документов (прием, увольнение, отпуск) и дается инструкция по подключению нового регистра к этому механизму.

03.03.2026    4617    YA_1100893639    1    

9
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Dorosh 179 27.10.26 14:04 Сейчас в теме
>> Отказ расширения конфигурации - это тихий сбой, который дорого стоит. Он иногда может случиться если обновить расширение динамически под нагрузкой.

Вариант решения проблемы - никогда не использовать демоническое обновление, ни для расширений ни для основной конфы не предлагать? Проще не создавать проблему чем потом героически и интеллектуально ее решать.
2. ksnik 728 27.10.26 14:14 Сейчас в теме
(1) Я привел один сценарий отказа, известное обстоятельство в том что расширения отказывают при плановых обновлениях типовой конфигурации (а это неизбежно). А обновлять динамически или не обновлять это вопрос который каждый для себя решает сам, бывают обстоятельства связанные с простоями и деньгами, когда не обновлять не выгодно для организации, в зависимости от обстоятельств. То есть совет никогда не обновлять динамически имеет ограниченное применение и не является безусловным решением задачи которая раскрывается в моей публикации. Я обновляю динамически расширения и не обновляю основную конфигурацию. Нагрузка тут очень важный фактор.
3. Ninel_S 208 27.10.26 20:14 Сейчас в теме
(2)
Нагрузка тут очень важный фактор.

+++
Для отправки сообщения требуется регистрация/авторизация