Проблема:
На одном из наших предприятий используется УТ Управление торговлей, редакция 11 (11.5.10.63).
Платформа - 1С:Предприятие 8.3 (8.3.23.1912)
В конфу загружена обработка интеграции СКБ-Контур - Диадок, которая с виду-то запускается, но при попытке передать документ на подпись, намекает на некоторую проблему.
Попытки обратиться в техподдержку СКБ-Контур привели к глумливому их ответу, насчет "Очистить серверный кэш", перезагрузить компьютер и вот все это.
Хотел бы я знать, понимает ли сама техподдержка СКБ-Контура, что такое "серверный кэш" или она просто радуется красивому слову.
Впрочем, ритуальные танцы с очисткой всякого рода кэшей, перезагрузкой сервера и прочее, были проделаны, но к успеху не привели.
Коллега даже с размаху установил новую и самую модную версию этой обработки.
Коронный совет любой техподдержки - выполнить ТиИ.
Разумеется, все это - тщета и суета сует.
Но делать-то что-то надо.
Делаем:
Развёртываем тестовую базу, на тестовом сервере, убеждаемся, что ошибка - на месте. Делаем вывод, что её появление не зависит от настройки сервера, регистрации базы в кластере, наличия пресловутого "серверного кэша" и всего вот этого, о чем нам сообщает техподдержка.
Разглядываем пациента.
Обработка, предоставленная нам поставщиком, представляет собой самодостаточную конструкцию, которая хранит в макетах свои запчасти, вытаскивая их при старте из этих макетов.
Поэтому, конечно, отладка затруднена.
Нельзя просто взять и поставить точку останова, с целью понять, что-же происходит внутри. Ну или там устроить "Остановку по ошибке"
Поэтому, настраиваем техножурнал, с целью поймать строку сбойного кода. Я совсем не мастер техножурнала, однако предположил, что мы ловим ексцепшены, обращения к SQL, а также SDBL, раз про него намекает исходное сообщение об ошибке.
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://v8.1c.ru/v8/tech-log">
<dump location="C:\1c\SPK_dumps" create="1" type="0" externaldump="1"/>
<log location="C:\1c\SPK_logs" history="12">
<event>
<eq property="Name" value="EXCP"/>
<eq property="p:processName" value="ugmetall_trade_2022_dev2"/>
</event>
<event>
<eq property="Name" value="SDBL"/>
<eq property="p:processName" value="ugmetall_trade_2022_dev2"/>
</event>
<event>
<eq property="Name" value="DBMSSQL"/>
<eq property="p:processName" value="ugmetall_trade_2022_dev2"/>
</event>
<property name="all">
</property>
</log>
</config>
Провоцируем ошибку и где-то в глубинах этого страшного стека вызовов находим:
Наблюдаем, что в темных глубинах есть обработка ВнешняяОбработка.КонтурДиадокСтандартУФ
Внутри модуля которой, в строке 2222 имеется "Если Выборка.Следующий() Тогда", в котором сбой и происходит.
Выгружаем оную обработку из макета (а нам еще следует догадаться, в каком макете она притаилась), и видим вот такое:
Функция ЗагрузитьМаркерКонфигурации()
Результат = Неопределено;
КлючОбъекта = "МодульДиадок";
КлючНастроек = "МаркерКонфигурации";
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("КлючОбъекта" , КлючОбъекта);
СтруктураОтбора.Вставить("КлючНастроек" , КлючНастроек);
СтруктураОтбора.Вставить("ИмяПользователя" , "");
УстановитьПривилегированныйРежим(Истина);
Выборка = ХранилищеОбщихНастроек.Выбрать(СтруктураОтбора);
Если Выборка.Следующий() Тогда
НайденноеЗначение = Выборка.Настройки;
ЭлементДопустимогоМаркера = ДопустимыеМаркерыКонфигураций().НайтиПоЗначению(НайденноеЗначение);
Если ЭлементДопустимогоМаркера <> Неопределено Тогда
Результат = НайденноеЗначение;
Иначе
ХранилищеОбщихНастроек.Удалить(КлючОбъекта, КлючНастроек, ИмяПользователя());
КонецЕсли;
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
Возврат Результат;
КонецФункции
Сразу посмотрим в синтакс-помощник и сообщим, что в отборе нужно задать ключ "Пользователь" а не "ИмяПользователя". Еще соображение, а также если мы отбираем по пустому имени пользователя то и удалять должны тоже по нему ?
Но черт с ним, пускай у СКБ-контура голова болит об их коде.
Нас волнует другое кино, сбой происходит на вызове метода Следующий() ХранилищаОбщихНастроек.
Еще интереснее, что ни до какого SDBL или тем более DBMSSQL, оно не доходит.
Что любопытно, если мы укажем просто Выбрать() без отбора, то код вполне себе работает.
Также оно работает, если в структуре отбора нет "КлючНастроек".
И вообще, сообщение насчет "CAST" наводит на мысль, что проблема с хранилищем общих настроек, но вся остальная конфа-то при этом исправно работает.
Что с этим делать?
Поиск по конфе по слову "ХранилищеОбщихНастроек.Выбрать(" показал, что такая конструкция в УТ 11.5 вообще не используется, а применяется Загрузить().
Точнее, найдено одно место и кого-то из коллег поджидает сюрприз
Варианты:
1. Вырезать вовсе обращение к ХранилищуОбщихНастроек, возвращать Неопределено, типа "я ничего не нашел", там выше по стеку вызовов предусмотрена обработка такого случая. Это мой выбор. Дешево. надежно, практично.
2. Залепить вот такое
Функция ЗагрузитьМаркерКонфигурации()
Результат = Неопределено;
КлючОбъекта = "МодульДиадок";
КлючНастроек = "МаркерКонфигурации";
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("КлючОбъекта" , КлючОбъекта);
СтруктураОтбора.Вставить("КлючНастроек" , КлючНастроек);
СтруктураОтбора.Вставить("ИмяПользователя" , "");
УстановитьПривилегированныйРежим(Истина);
//Выборка = ХранилищеОбщихНастроек.Выбрать(СтруктураОтбора);
//Если Выборка.Следующий() Тогда
// НайденноеЗначение = Выборка.Настройки;
// ЭлементДопустимогоМаркера = ДопустимыеМаркерыКонфигураций().НайтиПоЗначению(НайденноеЗначение);
// Если ЭлементДопустимогоМаркера <> Неопределено Тогда
// Результат = НайденноеЗначение;
// Иначе
// ХранилищеОбщихНастроек.Удалить(КлючОбъекта, КлючНастроек, ИмяПользователя());
// КонецЕсли;
//КонецЕсли;
Настройки = ХранилищеОбщихНастроек.Загрузить(КлючОбъекта, КлючНастроек,,"");
Если Настройки <> Неопределено Тогда
НайденноеЗначение = Настройки;
ЭлементДопустимогоМаркера = ДопустимыеМаркерыКонфигураций().НайтиПоЗначению(НайденноеЗначение);
Если ЭлементДопустимогоМаркера <> Неопределено Тогда
Результат = НайденноеЗначение;
Иначе
ХранилищеОбщихНастроек.Удалить(КлючОбъекта, КлючНастроек, "");
КонецЕсли;
КонецЕсли;
УстановитьПривилегированныйРежим(Ложь);
Возврат Результат;
КонецФункции
Загружаем заколхоженную нами служебную обработку в макет, откуда выгружали.
Загружаем Контур-ЭДО в "Печатные формы отчеты и обработки"
Ура, работает что первый, что второй вариант.
Заключение:
Проблема побеждена, документы на подпись передаются, ура.
Но все же, господа, что это было?
Любое обращение к ХранилищуСтандартныхНастроек.Выбрать(Отбор), если в отборе присутствует ключ "КлючНастроек", приводит к ошибке и падению клиентского сеанса.
При этом, в ТЖ не пишется даже события SDBL.
Причем в случае, пустого отбора, код вполне работает и все события в ТЖ, как положено. пишутся.
Это очень похоже на ошибку платформы?
Меня не покидает ощущение неправильности, прошу советов, как надо было сделать правильно.