gifts2017

Динамические подписки на события v.3

Опубликовал Владимир Литвиненко (VladimirL) в раздел Программирование - Инструментарий

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

 

Изменения в новой версии:

-  Добавлена управляемая форма подписки совместимая c интерфейсом "Такси" без использования модальных окон
-  Теперь в обычной и управляемой форме подписики на событие доступен конструктор запросов (только в толстом клиенте)
-  Устранена проблема со сбросом свойств объектов подсистемы при добавлении подсистемы в конфигурации на платформе 8.3



Особенности подсистемы

1) Подписки на события объектов можно добавлять и редактировать в пользовательском режиме, они вступают в действие почти мгновенно, без отключения пользователей и без необходимости каких-либо дополнительных действий.

В каждом сеансе код подписок будет читаться из БД один раз и помещаться в кэш - параметр сеанса (фиксированный hash-map). При возникновении событий, для которых предусмотрены подписки, но не чаще чем раз в 15 секунд, читается константа, хранящая последнюю дату и время изменения кода, и проверяется необходимость обновления кэша. Новый код вступит в силу не позднее чем через 15 секунд после его изменения и в то же время обращение к БД для чтения всего одной константы происходит достаточно редко, чтобы не сказываться на производительности системы.


2) Поддержка английского и русского языков снимает ограничение на использование подсистемы в нерусскоязычных конфигурациях. 


3) Процесс выбора объектов для новой подписки близок к тому, как это происходит в конфигураторе.

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

 

4) Для создания/редактирования подписки в тонком клиенте доступна только управляемая форма. В толстом клиенте для этого можно использовать на выбор обычную или управляемую форму, для чего в форме списка созданы специальные кнопки. По умолчанию в толстом клиенте открывается обычная форма, поскольку только она обеспечивает синтаксическую подсветку кода:

 

 


5) Существует возможность приостановить действие подписки выставив соответствующий флаг. Возможность задавать последовательность выполнения подписок на события через присвоение им числовых приоритетов. В порядке приоритетов выполняются сначала подписки, назначенные для конкретного объекта метаданных, затем для класса метаданных.


6) Есть возможность проводить отбор всех подписок, относящихся указанному источнику и производить поиск по тексту, содержащемуся в коде. Оба поля отбора текстовые, поиск регистронезависимый:

 

7) Если объект метаданных, для которого назначена подписка, будет переименован в конфигураторе, то необходимо переназначить источник подписки в пользовательском режиме. При открытии формы списка подписок производится проверка правильности имен метаданных, указанных в качестве источника. Все подписки, для которых обнаружено несоответствие источника и метаданных конфигурации выводятся в информационное окно:

 

8) Код подписки выполняется оператором "Выполнить", который выдает ошибку, если встречает оператор "Возврат". Это ограничение обходится через хранение двух версий кода. Одна отображается на форме и редактируется программистом. Другая будет исполняться при обработке событий. Она генерируется при записи подписки путем замены оператора "Возврат" на оператор "GoTo", метка для  которого добавляется в конец кода. Увидеть результат автозамены после записи можно в форме списка подписок:

 

 9) При запуске в толстом клиенте как в обычной так и в управляемой форме доступен конструктор запросов:


 

Ограничения подсистемы

1) Код задается в пользовательском режиме, где недоступна контекстная подсказка и отладка. Код выполняется в контексте своего общего модуля и его нельзя разбить на процедуры. Поэтому в пользовательском режиме лучше добавлять обработчики с относительно независимым алгоритмом.

2) Невозможно использовать инструкции препроцессору #Если ... #КонецЕсли. Код, расположенный в таких блоках просто игнорируется. Чтобы сгладить это ограничение в коде подписки доступна предопределенная переменная "КодИсполняетсяНаКлиенте"/"CodeIsExecutingOnClient". Если она равна Истина, значит исполнение кода идет в толстом клиенте, иначе - на сервере. Для конфигураций на управляемых формах это не актуально.

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

 

Разумеется, эти ограничения можно обойти просто используя стандартное добавление подписок через конфигуратор :) Эта подсистема нужна чтобы дополнить стандартные возможности платформы, а не заменить их.


 

 

Установка и настройка подсистемы

1) Скачиваем файл конфигурации. За исключением свойств самой конфигурации объединяем с конфигурацией нашей БД. Не забывайте при объединении проставить флажок и на самой подсистеме!

У вас в конфигурации появится независимая не включаемая в командный интерфейс подсистема des_DynamicEventSubscriptions, все объекты которой будут иметь префикс "des_".


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

 

4) Пользователям будут нужны права на объекты новой подсистемы:
     - получение и установку четырех параметров сеанса: des_CodeCachingDateTime , des_ConstantCheckDateTime, des_CachedCodeCollection, des_MapSourceRuEn
     - чтение справочника "des_DynamicEventSubscriptions" и константы "des_CodeChangeDateTime"
Поэтому надо либо дать роли "Пользователь", уже имеющейся в вашей конфигурации эти права, либо добавить всем пользователям роль "des_User". Программистам нужно дать полные права на эти объекты.


5) Подсистема способна работать в тонком клиенте. Но чтобы использовать конструктор запросов и иметь возможность открывать обычную форму с синтаксической подсветкой кода конфигурацию нужно запускать в толстом клиенте (управляемом или обычном приложении).

6) Язык, который вы хотите использовать выбирается в форме списка справочника "Dynamic event subscriptions". По-умолчанию выбирается тот, который установлен в поле "Вариант встроенного языка" для конфигурации. Язык влияет на интерфейс формы списка подписок, формы выбора источника события и определяет с применением какого языка будут создаваться новые подписки. Он не влияет на уже созданные подписки, для них язык определяется при создании и в дальнейшем остается неизменным:

 



Добавление новых подписок

Группы добавляются по желанию. Можно создавать отдельные группы для отдельных классов объектов. Может оказаться удобно создавать группы по прикладному назначению (допроведение, запреты изменения, заполнение):

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

Проверяем, работает ли подписка. Для этого на время проверки в код можно вставлять вызовы метода Сообщить(), выводящего диагностические сообщения.

 

 

 

 


 

Рекомендации

1) Если вы думаете, что могли допустить ошибку в коде, но по какой-то причине сразу добавляете подписку в рабочую базу, а не тестовую, то помещайте свой код в блок "Попытка Исключение". Необработанные исключения в них могут привести к отключению клиентского приложения. Неявной их обработки делать не стал, вы сами можете решить, обрабатывать исключения в своем коде или нет. Все таки сразу в рабочую базу лучше добавлять только простые подписки, где вероятность ошибки мала (например запрет записи/проведения по условию).

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

3) Работа на платформе ниже версии 8.2.16 не проверялась. Будьте внимательны при использвании этой и более ранних версий платформ.

 


 

 

К публикации приложено два файла - конфигурация des_v3.cf и выгрузка демо-базы des_demo_v3.dt, в которой есть несколько дополнительных объектов и подписок, определенных для них.


Ниже приведены скриншоты из реальной рабочей базы УПП 1.3.

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

Наименование Файл Версия Размер
des_v3.cf 64
.cf 83,27Kb
25.12.13
64
.cf 3 83,27Kb Скачать
des_demo_v3.dt 44
.dt 127,89Kb
25.12.13
44
.dt 3 127,89Kb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Александр Зубцов (iov) 10.11.13 02:15
Чрезвычайно полезная весчь...
2. Тимофей Шантин (ShantinTD) 11.11.13 09:01
3. ффф ыыы (zqzq) 11.11.13 10:45
В принципе можно и синтакс-подсказку и контекстную прикрутить к обычной форме, см.:
http://infostart.ru/public/72813/
http://infostart.ru/public/15126/
4. Андрей Сябренко (AzagTot) 11.11.13 13:14
Интересная разработка. Спасибо!
Взял на заметку))
5. Владимир Литвиненко (VladimirL) 11.11.13 14:42
(3)
В принципе можно и синтакс-подсказку и контекстную прикрутить к обычной форме, см.:
http://infostart.ru/public/72813/ http://infostart.ru/public/15126/

Необходимость иметь установленные библиотеки из MS Office - это жесткое ограничение. В многофункциональных "Инструментах разработчика" это уместно, но в этой маленькой подсистеме будет не очень. Да и объем кода, необходимый для поддержки контекстной подсказки скорее всего будет больше, чем объем кода в подсистеме сейчас.

Вообще конечно есть мысли по поводу дальнейшего развития подсистемы, раз она вызвала какой-то интерес. Было бы удобно иметь возможность вызывать конструктор запросов. Получать оповещения о подписках, для которых следует переназначить источник ввиду переименования или удаления метаданных. Реализовать объявление процедур в пользовательском режиме с возможностью их вызова. Это по идее не должно сказаться на универсальности. Очень хотелось бы избавиться от толстого клиента, но наверное не получится.
Если найду время на доработку - обновлю публикацию.
6. Семён Павлюков (7OH) 13.11.13 10:12
Конструктор запроса тоже легко реализовывается , например отдельной вкладкой с полем, где тип расширения стоит "язык запросов" - ну и дальнейшим взаимодействием этих двух полей.
7. Владимир Литвиненко (VladimirL) 14.11.13 05:07
Надо посмотреть как в "Инструментах разработчика" это сделано.
8. Данила Елистратов (CagoBHuK) 15.11.13 13:23
Плюс за проделанную работу.
10. Сергей Старых (tormozit) 19.11.13 11:29
Для тех, кому тема подписок интересна. У нас в компании 2iS давно сделана есть базовая конфигурация (Система 2IS) с динамическими подписками и алгоритмами (сервисами) в базе. Естественно это сделано на основе подсистемы ИР и ее возможности там используется очень широко.
В правой части скриншотов виден менеджер подписок, который позволяет задавать алгоритмы для обработки события выбранного сверху объекта применения на текущем уровне наследования, а также управлять их порядком. Слева видны формы списка алгоритмов (сервисов), форма элемента алгоритма и форма дизайнера (настройщика) формы. Отмечу, что подписки реализованы у нас для всех событий платформы, включая события форм и их элементов. Причем в большинстве случаев используется иерархия (наследование) типов объектов и можно задавать подписки на любом уровне этой иерархии. Также есть возможность создавать свои события.
Прикрепленные файлы:
11. Владимир Литвиненко (VladimirL) 19.11.13 13:08
(10) tormozit,
Вот это комплекс! Интересно, особенно про события форм и элементов. Динамические подписки серьезно облегчают поддержку баз, и если в вашей системе они возможны и для событий форм, то это конечно здорово.

Отдельно распространять эту подсистему не планируете?
12. Сергей Старых (tormozit) 22.11.13 10:50
(11) К сожалению выбранная стратегия развития нашей платформы не подразумевает классическое тиражирование. БОльшая часть кода и форм находится в таблицах БД. Таким образом мы получили максимальное удобство для разработки для проектов нашей компании, но получили сложности в тиражировании в обычном понимании. Фактически наша платформа состоит из подсистемы конфигурации (меньшая часть) и ряда системных данных в большом числе таблиц БД (бОльшая часть). Естественно у нас есть технология регистрации изменений, выгрузки/загрузки со сравнением системных данных с фильтрацией через обычные планы обмена. Однако сравнение перед загрузкой в БД обладает меньшей наглядностью, чем сравнение конфигураций. Также требуется ощутимое изменение мышления разработчика. Платформе нашей уже 2 года с окончания активного развития и где то 5 лет с начала ее активного развития.
Разрабатывать в ней в большинстве отношений конечно значительно удобнее чем в обычном конфигураторе (как говорят "душа поет").
RegrZ; RailMen; it-al; Evil Beaver; +4 Ответить
13. Елена Пименова (Bukaska) 22.11.13 11:00
(5) VladimirL, Богат мир разработок))) Смутило правда немножко название.. Но потом глянула статью и поняла о чем речь)))
14. Алекс Одинэсник (Alex1Cnic) 26.11.13 10:56
Да, нехилая разработка! плюс
15. Сергей Старых (tormozit) 26.11.13 20:20
Автору рекомендую поддержать ИР, если она установлена в конфигурации. Это значительно поднимет удобство разработки, а значит увеличит число пользователей.
16. Владимир Литвиненко (VladimirL) 27.11.13 04:29
(15) tormozit,
Это очень хорошая идея. Лучше, чем изобретать велосипед со своими конструкторами и прочим. Еще не изучал какой API есть у ИР, но постараюсь посмотреть в ближайшее время.

Еще хорошо бы совместимость с "Такси" предусмотреть на случай если программисту нужно только готовый код подписки вставить и не нужны навороты вроде подсветки синтаксиса и конструкторов. Всё равно все там будем... в смысле на "Такси" :)
17. Семён Павлюков (7OH) 30.11.13 01:37
Спасибо и за разработку и большое отдельное спасибо за идею с Возвратом из выполнить.
18. Семён Павлюков (7OH) 30.11.13 02:56
(5) VladimirL,
"Реализовать объявление процедур в пользовательском режиме с возможностью их вызова. "
Опробовал у себя возможности v8Unpack по отношению к внешним обработкам и их вызову из того же выполнить.
Сохраняем макет во внешнюю обработку, меняем текст модуля - вот тут можно и процедуры объявлять. Далее только вызвать надо.
Насколько применимо - смотрите сами.
19. Александр Зубцов (iov) 26.12.13 15:55
20. Александр Зубцов (iov) 26.12.13 15:58
Если нужны варианты для использования в виде тиражного решения велкам в личку.
21. Владимир Литвиненко (VladimirL) 26.12.13 17:14
(19) На самом деле я не знаю сколько еще буду развивать эту подсистему. Она делает то, что нужно на нашем предприятии. Дальше уже дело интереса и наличия времени :) Надо попробовать добавить еще пару функций из упомянутых в комментариях и отслеживать совместимость с новыми версиями платформы.

(20) Может быть я ошибаюсь, но кажется, что сравнение/объединение с cf-файлом это стандарт распространения подсистем для 1С:Предприятия. Другие способы незнакомы большинству программистов и могут вызывать недоверие.
22. Александр (МимохожийОднако) 01.01.14 09:53
23. bulpi bulpi (bulpi) 01.01.14 17:08
Реально очень круто. Только непонятно, зачем.
24. Владимир Литвиненко (VladimirL) 02.01.14 13:51
(23) Наверное мне действительно стоило меньше расписывать, как работает подсистема и больше внимания уделить тому, как ее применять :) Сейчас это можно понять в основном из скриншотов в конце, сделанных из базы УПП 1.3.

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

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

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

Благодаря кэшированию кода на базе с 250+ пользователей падения производительности не наблюдается. Расход оперативки на хранение кода в параметрах сеанса также невелик, хотя и подписок у нас добавлено не больше 100.



Разумеется при небольшом числе пользователей применять подсистему не имеет смысла, их легко выгнать. Скорее всего она не подойдет и для распределенной базы данных. Нет подписок на события элементов форм. Для всего этого нужно применять системы совсем другого уровня вроде упомянутой выше системы 2IS или СКАТ-Профессионал.
25. Клим (Ex) 19.01.14 07:35
Запись Плана обмена. Никаких подписок на план нет.
Ошибка при выполнении обработчика - 'ПередЗаписью'
по причине:
{ОбщийМодуль.des_ServerRichClient.Модуль(34)}: Поле объекта не обнаружено (DataExchange)
26. Игорь Дзеса (Kamikadze) 30.01.14 12:45
Попробую использовать ее.
27. Андрей Киреев (FractonKireyev) 05.02.14 14:17
Теперь Автору (с большой буквы) надо решить вопрос с тиражированием. И тогда все внедренцы ему низко поклонятся.
28. Семён Павлюков (7OH) 06.04.14 01:05
Можно попросить внести в следующий релиз пару приятных вещей?
1. Роль des_admin : программистам легче роль назначить, чем каждый раз настраивать роль полные права.
2. Под указанную роль можно добавить интерфейс для вызова справочника.
3. Раз уж полной интеграции с системой автоматически нет - в каждом событии проверять доступность роли des_user, дабы не иметь проблем с НОВЫМИ пользователями.
29. Семён Павлюков (7OH) 07.04.14 00:25
Procedure BeforeWrite_ExceptDocumetns(Source, Cancel) Export
//вот у ПланаОбмена нет такого свойства как ОбменДанными
Если Найти(Source.Метаданные().ПолноеИмя(), "ПланОбмена.") <> 1 Тогда
If Source.DataExchange.Load Then
Return;
EndIF;
КонецЕсли;

Procedure OnWrite_Objects(Source, Cancel) Export
//вот у ПланаОбмена нет такого свойства как ОбменДанными
Если Найти(Source.Метаданные().ПолноеИмя(), "ПланОбмена.") <> 1 Тогда
If Source.DataExchange.Load Then
Return;
EndIF;
КонецЕсли;
-----
в теме внешнего журнала на SQL уже обсуждали такое же.
Решение выше было выбрано как самое лучшее по бустродействию.
Возможно есть ещё места, но при наших обменах больше нигде не вылезло.