Rule with trigger "System started" does not run after changing rule file

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.

Regards
Bertram

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.

2 Likes

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 remember reading the thread but I get an email for all the issues and PRs and can’t remember where I saw the discussion. I think it was at https://github.com/openhab/openhab-core/issues/1637.

I would expect it to run when that rule is loaded, not all rules.

Hi all,

To reiterate what I said over on GitHub:

  1. 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.

  2. 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)

  3. 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)

Have you filed an issue? Even better a change like that would be pretty quick to make by clicking on the link at the bottom of the docs page.

Mentioning this on an issue that is closed on a completely different github repo is unlikely to be seen by the docs maintainers.

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.

I fully agree we obviously mean the same.

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?

I’ve found that much of the time either:

  • consolidating the rules into one where possible
  • storing state in Items
  • keeping those rules in text files
  • 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!

2 Likes

Just to share the workaround I created: Listen to the rules folder for updates and then update an OH item.

while inotifywait -e modify /etc/openhab/rules; do sleep 10;  curl --max-time 5 --fail --header "Content-Type: text/plain" --request POST --data "ON" "http://localhost:8080/rest/items/misc_reload_rules"; done &

The sleep time is to make sure the new changes are loaded before the trigger.

Inside the rule I have:

rule "Rule updated"
when
    Item misc_reload_rules received update
then
	logInfo("alarm","INIT")
        // Init stuff
end
2 Likes