After migration to Openhab 3.0 rules with trigger “System started” are no longer triggered when changing the file containing the rule. The rule neither runs when creating a new file nor when changing the file.
To reproduce the issue just create a rule like:
rule "system started"
when
System started
then
logInfo("System started", "System was started")
end
The rule works as expected when I run the rule explicit from the UI or by restart openhab.
2021-01-15 12:46:18.682 [INFO ] [hab.core.model.script.System started] - System was started
But it does not run when creating or changing the file containing the rule.
This is not a big issue when using openhab productive.
But it is very annoying during development.
The issue happend using a raspberry as well as within a docker container.
There are some issues open for this already. The problem is the System started trigger was changed to work more like what it’s supposed to, i.e. it runs when the system starts, more specifically when the system reaches run level 20. Run level 20 only happens once when OH starts so it doesn’t trigger your rules when they have been reloaded after OH has started.
This is actually a more correct behavior for a trigger called “System started”. I think there is talk of adding a new “Rule loaded” or something like that trigger. But for now, you’ll either need to restart OH or manually run the rule from the UI by clicking the play button.
Many thanks for your fast feedback. Unfortunately I was not able to find the related issues.
The idea of providing a trigger like “Rule loaded” sounds good.
Just an additional proposal. When using files to define rules beside the rules there are already sections for imports and variable declarations.
Instead or in additional to a trigger like “Rule loaded” you might also consider to allow statements to do along with the variable declarations.
This would fit well to the use-case of a complex variable initialization.
Beside the work around you mentioned there is one more quite dirty work around.
You could (miss-)use another event to fill the gap of the missing trigger along with a helper variable to avoid multiple execution.
var ready = false
rule "system started"
when
System started
or Time cron "0/10 * * * * ? *"
then
if (ready) {
return
}
ready = true
logInfo("System started", "System was started")
end
At least during development this could help. E.g. when doing a mass change in multiple files by search and replace it could be hard to always find and manually run all rules which are required to do all required initialization.
However I would of course prefer a proper solution like a new trigger for Rule (or should it be Rules) loaded.
I agree that a trigger to run the rule whenever the rules file is loaded (thus “rules” and not “rule”…though not ALL rules, just the ones in the same rules file) is important. If I edit rule A and save the file, it’s hard to know whether I need to run some or all of rules B, C, or D in the same file because, for instance, a timer needs to be recreated.
I can appreciate the redesign in 3.x (much of which seems to be for the better on my initial testing). But the documentation for rules still informs users that the “system started” trigger will refresh when the rules file is reloaded. Given the fact that it will not, the documentation should be updated, perhaps to note a difference in function between 2.x and 3.x. (Rules | openHAB)
The release notes make specific mention of breaking changes that require manual interaction from the user when upgrading from 2.x to 3.x. My view is that this is a breaking change (probably the only one preventing me from upgrading my production instance to 3.x) and should be mentioned as a warning in the release notes. (Releases · openhab/openhab-distro · GitHub)
When using files to define a couple of rules I expected the rules with trigger “Rule loaded” to run whenever that file was changed independent of which rule in the file was changed.
My understanding is that when a rule file is changed the old declarations of this file are invalidated and the new declarations get valid with there initial values.
A main use-case of rules trigger by “System started” or “Rules loaded” is to initialize the variables declared in the file. In case there are addition objects like timer which survives the re-load it is my responsibility as a developer to handle this.
In Rules DSL and UI rules there really isn’t a way to handle this actually, at least not well. The Timers will become orphaned. In Python and JavaScript there is a scriptUnloaded function you can define (there is a corresponding scriptLoaded I think too) where you can do stuff like cancelling those Timers before they become orphaned.
Correct and I think we mean the same thing. When you change any text config, everything that was defined in the file before gets deleted from OH and then that everything that is currently defined in that file gets recreated. So in that case, all the rules in that file were reloaded.
But, in the UI each rule gets loaded individually. There is no “file” and no bulk import. So when I modify a rule in the UI that would have a rule loaded trigger, I would expect that rule and only that rule to trigger.
From the UI view it is of course a bit different.
From the file usage I am pleased that reload would address the whole file and trigger each rule with the according trigger within file.
Off topic: I prefer to use files to define rules. But currently I even would not see a simple way to migrate to rules defined in the UI, because of the lack to have declaration being shared by multiple rules. Sometimes declaration I share (variables and functions) with multiple rules. If the rules are defined with the UI I see not who this could be managed.
My initial problem would be solved by a new trigger for “loaded”.
Is there already an issue to implement this feature?
calling other rules from a Script Action (you can pass data as part of the call)
libraries for sharing functions
You can save a variable between runs of a given Script Action/Condition. You just can’t share it between different scripts. And not all of the above is supported by Rules DSL.
There is supposedly a way using the ScriptExtension but I’ve not spent the time to figure that out yet.
Given that JavaScript supports functions it’s actually pretty easy to consolidate such rules into one ScriptAction and still keep the code logically separate.
Honestly, if you’ve a bunch of legacy .rules files, I would not recommend porting them to the UI unless you are also porting them to JavaScript or Python or Groovy too.
You’ll have to search and see. That issue I linked to above is where I saw the discussion which is the extent of my knowledge.
Fair enough. I would never have presumed to step on anyone’s toes to update the documentation…especially because I mostly don’t feel qualified enough to disagree with whoever wrote them in the first place. But I forked the rules documentation and created a new pull request for the change. Thanks!