gifts2017

Контролируемые механизмы

Опубликовал rtnm rtnm (rtnm) в раздел Программирование - Практика программирования

Автоматический запрет запуска в копиях рабочих баз механизмов, оказывающих внешнее воздействие

Введение

Я думаю, что многие сталкивались с такой ситуацией, когда после создания копии рабочей базы один или несколько механизмов в новой базе продолжали оказывать внешнее воздействие. К механизмам, оказывающим внешнее воздействие, можно отнести, например, различного рода обмены между информационными системами, уведомления пользователей и клиентов с помощью SMS или email.  Последствия от запуска таких механизмов не в рабочей базе могут быть разными - от легкой неловкости до сложнопоправимых ситуаций. В приниципе, для того, чтобы не возникало таких проблем, сделать нужно не так много - заблокировать регламентные задания, перенастроить механизмы или отключить их вручную. Но так называемый человеческий фактор все усложняет - люди увольняются, люди устраиваются, люди забывают.
Даже если представить, что нет человеческого фактора, то все равно все не так просто - механизмов может быть много и их перенастройка может быть утомительной.

Идея

Было бы хорошо, если бы определенным механизмам автоматически запрещался запуск в копиях рабочих баз.
А если бы надо было включить один из них, то только его и надо было перенастроить, а потом вручную разрешить ему запускаться.

Решение

В первую очередь для реализации идеи необходимо научиться различать копии одной и той же базы. Единственное, что их различает - это результат возвращаемый функцией СтрокаСоединенияИнформационнойБазы. С этой функцией есть некоторые особенности, связанные с тем, что она может возвращать немного разные строки подключения в зависимости от места ее выполнения. Поэтому я не использую напрямую возвращаемый ей результат. Функция ПолучитьКонтрольноеЗначение устраняет известные мне особенности.

Функция ПолучитьКонтрольноеЗначение() Экспорт    
    КонтрольноеЗначение = СтрокаСоединенияИнформационнойБазы();
    КонтрольноеЗначение = НРег(КонтрольноеЗначение);
    КонтрольноеЗначение = СтрЗаменить(КонтрольноеЗначение, ":1541", "");
    Возврат КонтрольноеЗначение;
КонецФункции

В конфигурации явно выделяются все механизмы, оказывающие внешние воздействия. Именно такие механизмы необходимо контролировать и поэтому я называю их контролируемые механизмы. Каждому контролируемому механизму (если быть точнее, то каждой его настройке) соответствует запись в справочнике "Контролируемые механизмы". В каждой настройке контролируемого механизма помимо прочего указывается и ссылка на соответствующую запись из справочника "Контролируемые механизмы".

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

Для разрешения запуска механизма используется следующая функция.

Функция РазрешитьЗапуск(КонтролируемыйМеханизм) Экспорт    
    КонтролируемыйМеханизмОбъект = КонтролируемыйМеханизм.ПолучитьОбъект();
    КонтролируемыйМеханизмОбъект.КонтрольноеЗначение = ПолучитьКонтрольноеЗначение();
    КонтролируемыйМеханизмОбъект.Записать();
КонецФункции

Для запрета запуска механизма используется другая функция.

Функция ЗапретитьЗапуск(КонтролируемыйМеханизм) Экспорт
    КонтролируемыйМеханизмОбъект = КонтролируемыйМеханизм.ПолучитьОбъект();
    КонтролируемыйМеханизмОбъект.КонтрольноеЗначение = "";
    КонтролируемыйМеханизмОбъект.Записать();
КонецФункции

Для того, чтобы определить разрешен или запрещен запуск механизма используется следующая функция.

Функция РазрешенЗапуск(КонтролируемыйМеханизм) Экспорт    
    Если Не ЗначениеЗаполнено(КонтролируемыйМеханизм) Тогда
        ВызватьИсключение "Не указан контролируемый механизм";        
    КонецЕсли;        
    Возврат (ПолучитьКонтрольноеЗначение() = КонтролируемыйМеханизм.КонтрольноеЗначение);    
КонецФункции

Есть еще одна процедура, она ничего не делает, если запуск механизма разрешен и вызывает исключение, если запрещен.

Процедура КонтрольЗапуска(КонтролируемыйМеханизм) Экспорт    
    Если Не РазрешенЗапуск(КонтролируемыйМеханизм) Тогда
        ВызватьИсключение "Запуск контролируемого механизма не разрешен";        
    КонецЕсли;        
КонецПроцедуры

Все эти процедуры и функции находятся в модуле менеджера справочника "Контролируемые механизмы"

Внедрение

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

//Получим настройки
Настройки = ПолучитьНастройки();   
//Контроль запуска
Если Справочники.КонтролируемыеМеханизмы.РазрешенЗапуск(Настройки.КонтролируемыйМеханизм) Тогда    
    //Выполнение
Иначе
    //Запуск запрещен
КонецЕсли;

Или так.

//Получим настройки
Настройки = ПолучитьНастройки();   
//Контроль запуска
Справочники.КонтролируемыеМеханизмы.КонтрольЗапуска(Настройки.КонтролируемыйМеханизм);   
//Выполнение

Мне больше нравится второй вариант.

Демонстрационный пример

Для того, чтобы было еще понятнее, я подготовил демонстрационный пример:

0. Скачайте КонтролируемыеМеханизмы.dt
1. Создайте пустую базу и загрузите в нее КонтролируемыеМеханизмы.dt
2. Запустите новую базу в режиме предприятия и откройте справочник "Контролируемые механизмы" - пока запуск демонстрационного механизма запрещен.

 Контролируемые механизмы

3. Откройте обработку "Демонстрационный механизм" и все равно попытайтесь запустите механизм - действительно, запуск демонстрационного механизма запрещен.

Контролируемые механизмы
4. Вернитесь в справочник "Контролируемые механизмы" и разрешите запуск демонстрационного механизма - запуск демонстрационного механизма разрешен.

Контролируемые механизмы
5. Вернитесь к обработке "Демонстрационный механизм" и запустите его еще раз -  действительно, запуск демонстрационного механизма разрешен.

Контролируемые механизмы
6. Выгрузите данные базы в .dt
7. Создайте еще пустую базу и загрузите в нее только что полученный файл .dt
8. Запустите новую базу в режиме предприятия и откройте справочник "Контролиремые механизмы" - запуск демонстрационного механизма автоматически стал запрещен.

Контролируемые механизмы

Заключение

Надеюсь, описанный в статье механизм пригодится вам. Спасибо за внимание.

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
КонтролируемыеМеханизмы.dt
.dt 26,60Kb
19.05.14
2
.dt 26,60Kb 2 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Андрей Киреев (FractonKireyev) 21.05.14 10:43
Идея не нова и не оригинальна. Я использовал этот-же принцип несколько лет назад при обмене данными. Сразу оговорюсь - идею я тогда тоже где-то вычитал (не помню где).

Но автору всё-равно спасибо за подробное объяснение принципов контроля - я встречал спецов с дружественных франчевых фирм, которые по этим граблям ходили и не могли понять сути проблемы (у них тогда после обмена обнаруживалась куча битых ссылок). Может быть, эта статья уменьшит количество таких проблем.
2. mikhailovaew (mikhailovaew) 22.05.14 16:34
КонтрольноеЗначение = СтрЗаменить(КонтрольноеЗначение, ":1541", "");

а почему бы не убирать любое значение порта?
3. rtnm rtnm (rtnm) 22.05.14 18:24
(2) mikhailovaew, порт 1541 является портом по умолчанию для менеджера кластера, если при подключении к базе не указывать его явно, то будет использоваться именно он. Может случиться так, например, что при создании базы в кластере порт явно не указывали, а при подключении уже существующей базы порт 1541 указали, тогда получится, что в зависимости от места выполнения функции СтрокаСоединенияИнформационнойБазы порт 1541 может быть указан, а может быть не указан в возвращаемом ей результате. Указание порта менеджера кластера отличного от 1541 является обязательным, поэтому он будет присутствовать всегда в результате возвращаемом функцией СтрокаСоединенияИнформационнойБазы и удалять его нет необходимости.
4. Виталий Барилко (Diversus) 23.09.15 16:50
(0) Этот способ содержит ошибку, на которую когда то попался и я.
Все дело в том, что может быть такая ситуация, когда сервер может быть представлен несколькими способами и строка соединения с ИБ будет разной для одной информационной базы!
Например, в домене можно представить сервер 1С сразу несколькими способами:

1) server
2) server.local
3) 192.168.1.10 (ip сервера 1С)
4) server:1541
5) ...

И все способы будут работать. Не так давно был глюк в одном из наших решений, которое использовало данный подход когда из под пользователя все работало как надо, а из фонового задания не запускалось в следствии того, что фоновое задание считало что оно работало с сервером server.local (в домене)!

Переделайте подход, иначе могут быть ошибки, которые трудно будет найти.
Мы пошли путем, когда в "КонтрольноеЗначение" записывалось через точку с запятой все возможные представления сервера 1С и это помогло решить проблему.
5. rtnm rtnm (rtnm) 24.09.15 08:44
(4) Diversus, спасибо за замечание, такая ситуация действительно может быть, конкретно для нас она не страшна, так как если в рабочей какой-нибудь механизм вдруг не заработает, то будут вызываться исключения, которые увидят многие.
6. Андрей Акулов (DrAku1a) 20.10.15 02:13
Я использовал аналогичный подход, но различие делал только по имени базы (то, что в Ref=), для копий баз - всегда делается своё имя, с приставкой или окончанием "_test_", "_copy_" и т.п., так что всегда можно различить. Это помогает никогда не запускать регламентные задания в копиях.
И ещё совет - при запуске, если определил, что база является копией - выведи это в заголовок "ЭТО КОПИЯ "+ТекущийЗаголовок+" ЭТО КОПИЯ!!!" - и сам не спутаешь базу с оригиналом, и если что не так будет с рабочей базой - тебе юзеры сообщат (было дело).
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа