Авто-восстановление "битых ссылок" при обменах с несколькими базами данных в режиме управляемых форм


В процессе исполнения проектов консолидации данных из разных источников, возникновение «битых ссылок», особенно для закрытых периодов и действующих бизнес-процессов, могут быть крайне нежелательными в конкретный момент времени. Ясно, что специалисты со временем нормализуют обмены, восстановят утраченные по ошибке записи, но в моменте это не быстро, и необходим способ решения, который позволит продолжить производственный процесс на уровне продвинутого пользователя.

Сформулируем требования к решению:

— решение не должно требовать изменения типовых форм и объектов;

— инструмент решения должен быть доступен пользователю в точке обнаружения проблемы на расстоянии «одного клика»;

— исполнитель не должен обладать квалификацией разработчика при исправлении ошибки.

Сложности:

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

Блуждание в отладчике выявило возможность, которая позволяет решить вопрос лаконично и универсально.

Техническое решение:

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

— Создать обработчик в подписке, который определит ошибочный случай и восстановит запись объекта, которую предоставит пользователю в штатном окне.

Способ использования:

Пользователь встречаясь с указанием на потерянные данные по ссылке, выполняет стандартную команду открытия формы потерянного элемента. Система автоматически создает объект в системе, со ссылкой восстановленной из доступных сведений, наименование помечает в формате "Восстановлен: ххххх", где ХХХ — представление внутреннего идентификатора элемента и открывает текущую форму справочника. Если у оператора сеанса есть права на изменение элемента, он может вручную заполнить критичные сведения, и продолжить рабочую эксплуатацию системы. Далее инцидент в рабочем порядке обрабатывается сотрудниками ИТ-отдела.

Исходный текст модулей:

//Обработчик подписки на событие
Процедура ОбработкаПолученияФормыСправочников(парИсточник, парВидФормы, парПараметры, парВыбраннаяФорма, парДополнительнаяИнформация, парСтандартнаяОбработка) Экспорт
Перем пКлюч;

УстановитьПривилегированныйРежим(Истина);
Если парВидФормы = "ФормаОбъекта" Тогда

Если парПараметры.Свойство("Ключ", пКлюч) Тогда //Существующий элемент или создание нового?

пГУИДБитойСсылки = артисСервер.ГУИДБитойСсылки(пКлюч.Ссылка);
Иначе

Возврат;
КонецЕсли;

Если пГУИДБитойСсылки <>  Неопределено Тогда

Если парПараметры.ЭтоГруппа Тогда

пОбъект = парИсточник.СоздатьГруппу();
Иначе

пОбъект = парИсточник.СоздатьЭлемент();
КонецЕсли;

пОбъект.УстановитьСсылкуНового(парИсточник.ПолучитьСсылку(Новый УникальныйИдентификатор(пГУИДБитойСсылки)));
пОбъект.ОбменДанными.Загрузка = Истина;
пОбъект.Наименование = "Восстановлен: " + парПараметры.Ключ.Ссылка;
пОбъект.Записать();

Сообщить("Восстановлена запись удаленного элемента, заполните реквизиты и сохраните объект!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры

// Возвращает строку-ГУИД из первичного сообщения системы, например: <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824)
// Параметры:
// парНачальноеПредставлениеУдаленнойСсылки - строка вида: <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824)
Функция ПолучитьГУИДПоПредставлениюУдаленнойСсылки(парНачальноеПредставлениеУдаленнойСсылки) Экспорт

пГУИДУдОбъктаСтр = СтрЗаменить(СокрЛП(парНачальноеПредставлениеУдаленнойСсылки),"<Объект не найден> (","");
пГУИДУдОбъктаСтр = СтрЗаменить(пГУИДУдОбъктаСтр,")","");
пГУИДУдОбъктаСтр = СтрЗаменить(пГУИДУдОбъктаСтр,"0x","");
пГУИДУдОбъктаСтр = Сред(пГУИДУдОбъктаСтр, Найти(пГУИДУдОбъктаСтр,":")+1, СтрДлина(пГУИДУдОбъктаСтр));
// Преобразуем GUID
Возврат Сред(пГУИДУдОбъктаСтр,25,8)+"-"+Сред(пГУИДУдОбъктаСтр,21,4)+"-"+Сред(пГУИДУдОбъктаСтр,17,4)+"-"+Сред(пГУИДУдОбъктаСтр,1,4)+"-"+Сред(пГУИДУдОбъктаСтр,5,12);   //и получаем ГУИД = 05dbe824-a4c6-11dd-bf56-00145e3710ab
КонецФункции

// Проверяет ссылку на признак <Объект не найден>
// В случае отсутствия элемента, создает текстовый параметр для Новый УникальныйИдентификатор()
// этот способ работает быстрее, чем попытка создания объекта, как это предлагается в некоторых рекомендациях
// Параметры:
// парСсылка - ссылка системы, для которой необходимо создать объект, в случае если объект удален
// Возврат:
// Неопределено  -  ссылка реальная и не требует создания экземпляра или
// НормальныйГУИД, готовый для: Объект.УстановитьСсылкуНового(Новый УникальныйИдентификатор(УникальныйИд));
Функция ГУИДБитойСсылки(парСсылка) Экспорт

пПредставлениеСсылки = СокрЛП(парСсылка);
Если Лев(пПредставлениеСсылки, 20) = "<Объект не найден> (" Тогда

Возврат ПолучитьГУИДПоПредставлениюУдаленнойСсылки(пПредставлениеСсылки);
Иначе

Возврат Неопределено;
КонецЕсли;
КонецФункции

Спасибо всем за внимание.

5 Comments

  1. Mantis

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

    Reply
  2. SvkMaster

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

    ИТ отдел в общем случае обычно не владеет требуемым содержимым такой ссылки, поиск ее, это обращение к ключевым пользователям и игра в «испорченный телефон», где ИТ специалист так же лишен инструментов восстановления и должен что-то изобретать.

    Пример решения в статье, позволяет «залатать» пробел на уровне квалифицированного пользователя, который «руками» не влезая в какие-то дебри, создает недостающий элемент данных и содержание, после чего производственные задачи продолжаются, а ИТ-спецы параллельно решают задачу обмена и профилактики возникшего инцидента.

    Reply
  3. dsdred
    Функция ГУИДБитойСсылки(парСсылка) Экспорт

    пПредставлениеСсылки = СокрЛП(парСсылка);

    Если Лев(пПредставлениеСсылки, 20) = «<Объект не найден> (» Тогда

    Возврат ПолучитьГУИДПоПредставлениюУдаленнойСсылки(пПредставлениеСсылки);

    Иначе

    Возврат Неопределено;

    КонецЕсли;

    КонецФункции

    А где поиск «битой ссылки» то?

    Если наименование объекта начинается на «<Объект не найден> («, то Вы вполне можете и не «битую ссылку» ухватить.

    Почитайте комментарии к этой статье https://infostart.ru/public/175898/

    Reply
  4. SvkMaster

    (3) да, есть небольшой риск для случая, если элемент имеет такое представление, но я иду на него сознательно.

    ПолучитьОбъект() приводит к чтению объекта целиком из базы, в некоторых случаях, это приводит к существенной потере производительности (кто-то видел как работает RLS на больших данных?). Если интересно, можно поменять на получение объекта, но я бы не стал этого делать, так как вероятность в реальном контексте около нуля, а накладные расходы будут постоянными (уже не раз подобные проверки в типовых продуктах пришлось переписать).

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

    Reply
  5. SvkMaster

    (3) возможно, внимания заслуживает вариант с последним сообщением:

    Если ЗначениеЗаполнено(Ссылка) Тогда
    Если ЗначениеЗаполнено(Ссылка.ВерсияДанных) Тогда
    Сообщить(«Живая ссылка»);
    Иначе
    Сообщить(«Битая ссылка»);
    КонецЕсли
    Иначе
    Сообщить(«Пустая ссылка»);
    КонецЕсли;
    

    Показать

    попробую, сообщу о результате.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *