Вопросы по модулям для wb-rules

Добрый день.

Есть несколько вопросов/уточнений по работе модулей для wb-rules.

  1. Правильно ли я понял, что скрипт модуля выполняется в момент загрузки правила, которое использует этот модуль?
  2. Порядок загрузки модулей идет исходя из порядка загрузки правил, использующих этот модуль?
  3. Что происходит, если файл с модулем меняется? Он автоматически перезагружается? Если да, то по по какому принципу?
  4. При перезагрузке модуля, перегружаются ли правила, которые его используют?
  5. В модуле есть параметр expotrs.static, общий для всех экземпляров модуля. Что происходит с ним в момент перезагрузки модуля?
  6. Происходит ли что-то с expotrs.static в момент перезагрузки правила, которое использует этот модуль?
  7. На сколько корректно в теле модуля добавлять в глобальный контекст global._proto какие то функции? В частности писать что-то вроде такого:
global.__proto__.Thermostat = function(...) {
  this.active = false;
  this.heating = false;
  ...
  // описание класса через прототип, создание виртуального устройства
  ...
}

и потом в правиле писать

require("thermostat_module");
var thermostat1 = new Thermostat (...);
  1. Да.
  2. Да.
  3. Нет. Он обновиться только когда обновите файл правила, к которому он подцеплен. Если мне память не изменяет, то он обновляется сразу для всех скриптов, главное инициировать это обновление. Поэтому когда я меняю модуль, то потом меняю файл правил, чтобы изменения вступили в силу. Меняю буквально добавлением/удалением пробела в произвольном месте.
  4. Нет.
  5. Остаётся неизменным на сколько я помню. Поэтому у меня такая хитрость используется:
var DefinedVersion = "1.4"; // При редактировании этих переменных необходимо менять версию, чтобы переопределять глобальные пемеремные

if (module.static.DATA === undefined || module.static.DATA.version != DefinedVersion) {

	module.static.DATA = {

		"version" : DefinedVersion, // Версия файла
		"AllPowerOff" : false, // Полное отключение всех систем и питаний по аварии/пожару
		"NoInputPower" : false, // Нет входного питания потребителей (без детализации причины)
		"MainPowerOn" : false, // Включена сеть в доме (независимо от наличия питания на вводе)
		"BSMainPowerOff" : false, // Флаг перехода на аварийное питание и обратно
		"ONWaterPower" : false, // Включить питание ПЧ водоснабжения
		"OFFWaterPower" : false, // Отключить питание ПЧ водоснабжения
		"MainPowerOnRuleId" : 0, // Объект правила управления мастер-выключателем
		"MainWaterRuleId" : 0, // Объект правила управления водоснабжения
		"DINLastStates" : {}, // Состояния входов предыдущие (для логирования)

	};

}

У меня только сомнения, что будет, когда вся служба правил перезапускается, то есть сервис, тут зуб не дам. А просто при изменении модуля он никак не меняется, и отдельных правил тоже.
6. Ответил в 5.
7. Не знаю, не использую global.proto, ибо модули его же и заменяют.

Добрый день!

Прошу уточнить, актуален ли ещё ваш вопрос? Остались ли ещё какие-либо моменты, в которых нужна помощь? Готов помочь!

Добрый день.

В принципе на большинство вопросов ответили, но было бы здорово услышать от вендора все ли так как описал Александр.

  1. Модуль сам не перезагружается, только если перегружается правило, которое его использует.
  2. Если несколько правил использует модуль, то нужно самому вручную перегружать эти правила.
  3. Если два правила использует один модуль, и перегрудить одно правило, второе правило продолжит использовать старый модуль? И что в этот момент будет происходить с export.static?
  4. Пролить свет на поведение export.static при частичной или полной перезагрузке модуля, при перезагрузке сервиса wb-rules.

Ну и про 7 пункт про использование global.__proto__ (чтобы использовать глобальные функции и конструкторы).

Добрый день!

Модуль сам не перезагружается, только если перегружается правило, которое его использует.

Верно — только правила перезагружаются.

Если несколько правил использует модуль, то нужно самому вручную перегружать эти правила.

Не совсем: если вы изменили и сохранили хотя бы одно правило, перезапускается вся служба wb-rules, а значит, все правила перезапускаются автоматически.

Подробнее про поведение wb-rules и доступный функционал описано в данной статье.

Тут мне кажется вы не правы

Провел эксперимент.
Создал модуль

//test_module.js
var static = module.static;
log(">>>>[MODULE:{}] Initializing from rule '{}' (static: {})", module.filename, __filename, JSON.stringify(static));

var counter = static.counter || 0;
static.counter = ++counter;

exports.counter = counter;
exports.static = static;
log(">>>>[MODULE:{}] Initialized from rule '{}' (static: {})", module.filename, __filename, JSON.stringify(static));

и два правила

//rule_a.js
log(">>>>[RULE:{}] Initializing", __filename);
var module = require("test_module");
log(">>>>[RULE:{}] module global counter = {}, (module static: {})", __filename, module.counter, JSON.stringify(module.static));
//rule_b.js
log(">>>>[RULE:{}] Initializing", __filename);
var module = require("test_module");
log(">>>>[RULE:{}] module global counter = {}, (module static: {})", __filename, module.counter, JSON.stringify(module.static));

при перезагрузке сервиса целиком вижу в логах:

wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_a.js] Initializing
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initializing from rule '/etc/wb-rules/rule_a.js' (static: {})
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initialized from rule '/etc/wb-rules/rule_a.js' (static: {"counter":1})
wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_a.js] module global counter = 1, (module static: {"counter":1})
wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_b.js] Initializing
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initializing from rule '/etc/wb-rules/rule_b.js' (static: {"counter":1})
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initialized from rule '/etc/wb-rules/rule_b.js' (static: {"counter":2})
wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_b.js] module global counter = 2, (module static: {"counter":2})

меняю правило rule_a, нажимаю сохранить.
В логах переинициализируется только это правило

wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_a.js] Initializing
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initializing from rule '/etc/wb-rules/rule_a.js' (static: {"counter":2})
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initialized from rule '/etc/wb-rules/rule_a.js' (static: {"counter":3})
wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_a.js] module global counter = 3, (module static: {"counter":3})
wb-rules[27714]: INFO: reloading file: /etc/wb-rules/rule_a.js

тут так же можно увидеть, что контекст module.static сохраняется.

Дальше я изменил модуль (убрал увеличение счетчика), сохранил. Правила не перегрузились.
И потом снова изменил правило rule_a и сохранил.

В логах видно, что правило rule_a подцепила новый модуль. Общий контекст module.static сохранился.

wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_a.js] Initializing
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initializing from rule '/etc/wb-rules/rule_a.js' (static: {"counter":3})
wb-rules[27714]: INFO: [rule info] Changed module, doesn't change counter
wb-rules[27714]: INFO: [rule info] >>>>[MODULE:/etc/wb-rules-modules/test_module.js] Initialized from rule '/etc/wb-rules/rule_a.js' (static: {"counter":3})
wb-rules[27714]: INFO: [rule info] >>>>[RULE:/etc/wb-rules/rule_a.js] module global counter = 3, (module static: {"counter":3})
wb-rules[27714]: INFO: reloading file: /etc/wb-rules/rule_a.js

При полной перезакрузке сервиса wb-rules общий контекст module.static обнуляется, что в принципе ожидаемо.

Пошел чуть дальше. Добавил в модуль функцию test()

exports.test = function (){
    log("!!![MODULE:{}] Text call from module V1 from rule '{}'", module.filename, __filename);
} ;

и добавил в обоих правилах вызов каждые 5 сек

setInterval(function (){
    module.test();
}, 5000);

стали сыпатья такие логи

wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V1 from rule '/etc/wb-rules/rule_a.js'
wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V1 from rule '/etc/wb-rules/rule_b.js'
wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V1 from rule '/etc/wb-rules/rule_a.js'
wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V1 from rule '/etc/wb-rules/rule_b.js'

поменял в модуле строку на V2, поменял и сохранил модуль rule_a
Правило rule_b продолжило использовать старый модуль, правило rule_a уже новый.

wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V1 from rule '/etc/wb-rules/rule_b.js'
wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V2 from rule '/etc/wb-rules/rule_a.js'
wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V1 from rule '/etc/wb-rules/rule_b.js'
wb-rules[10319]: INFO: [rule info] !!![MODULE:/etc/wb-rules-modules/test_module.js] Text call from module V2 from rule '/etc/wb-rules/rule_a.js'

Сам спросил, сам делаю выводы =) Вдруг кому-то понадобится, в документации это поведение не описано.

  1. Модуль сам не инициирует перезагрузку правила, это происходит только при перегрузке самого правила.
  2. Чтобы правило стало использовать новый модуль, нужно его перегрузить (нажать сохранить, или перегрузить весь сервис)
  3. Правило будет продолжать использовать старый модуль, пока не перезагрузится.
  4. Контекст module.static создается при первой загрузке модуля, сохраняется при частичных перезагрузках правил и изменении кода модуля, обнуляется только при полной перезагрузке сервиса wb-rules.

Закину тогда предложение в копилку “когда нибудь возможно сделаем” =)
Предлагаю чуток поменять концепцию перезагрузки модулей:

При изменении модуля (файла с модулем) автоматически перезагружать все правила, которые его используют.
При этом возможно обнулять его общий контекст module.static.
Предположу, что все зависимости модуля можно вытащить и запомнить в реализации require().

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

Или в упрощенном варианте - просто перегружать весь сервис, но это наверное слишком кардинально.

1 лайк

Добрый день!

Направил вашу идею в таблицу предложений. Спасибо за идею!

Остались ли еще вопросы?

Все вопросы прояснил, спасибо

1 лайк