[Solved] Postponed rule execution? Do rules get put on stack?

This is correct. There is no way round it, the vast flexibility of openHAB does require some technical skills and the learning curve is steep.
Part of that flexibility is that if you dislike DSL rules you can use other rules setups. Look into NodeRed.

The distinction is that queuing events and activities is a design feature, not an error. By design, this system is intended to run on underpowered cheap hardware and cope as well as it can. That necessitates this kind of action.

If you want to write rules to ignore events under some circumstances, that’s your business, it’s no problem. You’ve just done one. There are other ways to do it too.

If someone else wants to write a rule that counts how many times you can push a button in a minute, they can do that without fear of missing one.

If you want to reduce the number of rule threads to 3, you can.

So far as I know there is no simple way to limit the number of times you can trigger a given rule “simultaneously”.
But here comes openHABs flexibility …

It would be possible to construct some complicated mechanism involving reentrant locks and a counter if you really wanted it.
Note, that there is nothing inherently wrong with using reentrant locks - BUT it’s a complete arse to develop, because
(a) you have to reeaally think about multithreading and
(b) when you make a tiny error in your rule you’ve “lost” the lock (or rather,the unlock) … making thorough development of anything non-trivial very difficult.
I would not recommend it and see no value in it here.

@hoomee I would look at the expire binding personally for this task.

I use it for my motion detector. If motion gets triggered on then the light switch gets updated. This intern updates the expire timer.

This in my mind is an alternate way to handle the problem and I believe it takes some complexity out of the rule.

2 Likes

Yes. But only if you write your rules in a way that supports that. Long running rules do not allow that.

To avoid long running rules, you must use timers instead of sleeps.

I don’t know how to answer that. It runs one second from now (based on your example). Exactly what runs depends on what code you put between the []. If you want to log out “hello world” one second from now:…

createTimer(now.plusSeconds(1), [|
    logInfo("test", "hello world")
])

The stuff between [ and | is how you world pass arguments to the that little block of code, which you don’t have to do for timers so you will usually either see the | omitted or nothing between the [ and |. To see an example when full explanation where stuffy is put been the [ and| see Reusable Functions: A simple lambda example with copious notes.

tl:dr, because the underlying programming language offers it. There is no way to hide that it exists not any way to prevent it’s use. And in certain circumstances, it can be useful, so long as the sleeps are short (fractions of a second).

You can find lots of stuff on this forum that either were never right, never a good idea, or is no longer the best way. It’s hard enough keeping up with the docs let alone going around and cleaning up everyone’s forum postings. Pay attention to the age of the post. If it’s more than a year old, look for more recent examples of you can. There might be a better way.

Thank you, I will check that, just to understand it better.

Thanks for the idea, but if I got you right, anytime you turn the light on, it will turn off after given time.
I want to have the possibility to turn it on manually without expiring. I use “expire” on few other lights though.

So it’s there for passing the arguments. It seems to be exactly the answer to my question. Thanks.

Sorry for bothering you, but I have some cron invoked rules (midnight in that case) and I’ve read the advice somewhere to make the thread sleep for second or two just to let Astro binding to recalculate times of day.
Also some system stuff may be happening at midnight.
Would you consider this a valid point?
Or is there a better way of how to write a rule to be run at midnight? (beside the obvious one to make it run at 0:01)

Thinking about it I have another question. Do timers - invoked from withing a rule - live outside the rule? In other words: the rule is executed and finished but the timer continues to count down in a separate thread?
If not, how does it work?
If yes: wouldn’t my new rule with timers, the one I have written above, also call many timers and wouldn’t they end after some time with blinking light? If not, can you explain why?

And one last (hopefully) question. In a rare case there are 10 different, good written, rules called simultaneously - will execution of the 6th and next be blocked until the 1st is closed? If there are timers in each of the hypothetical rules, the execution will be almost immediate? (in seconds?)

Why wouldn’t you do that? It costs nothing.

Nearly. A separate system manager looks after the scheduling. createTimer() really just registers “run this code at 0845 please”. No thread is consumed until it executes.
The rule that registered it has long since exited.

Look at the rule again. If the timer already exists, a new one is not made. (consider what the ‘handle’ being null means here)

@rossko57 Thanks for the explanations.

Now, I see that :slight_smile:
I assume the timer is identified with its name and not with the process ID.

It costs nothing indeed, that’s why I considered it obvious, but the idea was not mine, remember?
I don’t know why the author chose it this way. I can only change my rule now and hope it won’t break anything.

I have deleted all sleep times from all my rules now, and I have another problem.
One rule (let’s call it Rule 1) should only trigger some action if it is already “night”. The other rule (let’s call it Rule 2) takes about 90 msec to check and write “night” to the variable (the one needed to accomplish my action in Rule 1). Both rules are triggered by the same astro-event.
(Rule 1 depends on the output of Rule 2)

Considering:

and my 90 msec delay (87 msec in the last log to be precise),
will 100 msec delay be always sufficient? Or is it possible that sometimes, due to heavier load for instance, Rule 2 would get more delay, so Rule 1 wouldn’t work as intended?

I think/imagine the Rule 1 takes also some time (few msecs?) to execute, so it exits/ends at some point after the triggering effect, in fact diminishing the difference a little (probably little less than 87 msec), but is 100 msec enough? Will it be 100% reliable?

Can’t you concatenate then into one rule? Where the one that checks if it’s night runs last. Then you can use a variable instead of an item temporarily (updating an item and then reading it right after is not reliable, but you can still update it for later rule runs of course).

I believe it’s best practice to do this for rules that share the exact same trigger, unless they are completely independent.

1 Like

Triggering two processes from the same event is a design choice, perfectly acceptable.

If process B relies on some output of process A however, you have designed in a race condition. Unpredictable outcomes.

Giving one process a head start in the race - adding a delay - improves your odds, but is not a cure. The longer the delay, the better the odds, but still no guarantee.

The way to make it entirely predictable is to make it a relay race; process B triggered not from the original event, but from process A.

These truths I hold to be self-evident :wink:

2 Likes

Well, most probably I could, but they are completely independent. Rule 1 is triggered by and responsible for quite other events. But you got me thinking about design and…
is it possible for a rule to be triggered by a variable change/update?
So instead of triggering Rule 1 by the same astro-event, it could start only when the variable changes to “night”?

No, but Items are available to you.

OK, so basically I’d need a virtual switch, which is ON when the variable is set to “night”?
I can do it only from Rule 2 (the one responsible for updating the variables from astro-events)? or is there any other way?
Then I trigger Rule 1 from that virtual switch, correct?

As it’s getting more and more complicated :wink: do you know of a good way to document my setup? So I don’t loose track of those dependencies…
I’m afraid that when I for whatever reason have to recreate or slightly change it, I won’t be able to follow all the dependencies. Like what was that switch here for? Shall I remove it completely or will the house burn if I do it?

With little idea of what you’re trying to do, I can’t advise much.
Using virtual Items to represent stuff like “nighttime” is pretty standard practice, it’s then available to any rule in the system for any purpose - command, update, interrogate, trigger from.

For documentation I assume I’ve been run over by a bus and dropped the paperwork down a drain.
As I develop rules I simply add explanatory comment lines. Costs nothing.
I use mostly xxx.items and xxx.things files, which allow for comments about the stuff defined there. Relationships, purpose, naming conventions, etc.
What PaperUI users do, I don’t know.

Sample from one of my items files

// GENERAL.ITEMS

// NAMING CONVENTIONS
// dt_xxx   DateTime item
// sw_xxx   Switch item
// ct_xxx   Contact item
// nm_xxx   Number item
// sg_xxx   String item
// v_xxx    virtual item, any type

// for restore on startup etc.
Group gRestore "for restore on startup"
Group gChart "for graphing numeric data"
Number nm_chart_period "Graphing period" <line> (gRestore)

//  switch to indicate darkness by rule
Switch vsw_Darkness "Nighttime [%s]" <dark>
// ALARMS status
// coded status 0=fault 1=disarmed 2=partset 3=fullset 4=ringing   not all may be implemented in hardware
Number vnm_Fire "Fire Alarm [MAP(alarms.map):fire%s]" <ifire> (gRestore)
Number vnm_Intruder "Intruder Alarm [MAP(alarms.map):intruder%s]" <ialarm> (gRestore)

Thank you.
Apart of my layman’s naming patterns (and having multiple files for items of different kind), that’s what I’m trying to do already, but even if I write a comment in switches for instance and forget to add a comment in the rule, there is no way to trace it back. I guess I’ll have to live with it.

I have a similar usecase as yours (bet many users do) where I have a Switch item named Daylight that gets set to ON when Astro binding triggers sunrise and OFF at sunset. Then I can query this item in other rules that depend on it. For me this makes the code quite self-documenting:

if (Daylight.state == ON) {
   // Do stuff
}

If your Rule 1 is triggered by sunrise/sunset and is also dependant on the state of your Nighttime item you could change the trigger to Nighttime changed from OFF to ON.

1 Like

Have you seen Design Pattern: Time Of Day? That’s one of the of the reasons that DP exists. Process time of day events in only one place and update an Item with the result (i.e. the time of day). Everywhere else that cares about the time of day triggers on that Item changing or checks the state of that one Item.

This should make things much simpler over all. Need to add another time of day that you care about? You’ve one place to look and edit. Need to have another Rule that needs to know the time of day? Just check the one vTimeOfDay Item.

And if you use meaningful names for your Items, the name of the Item itself should tell you what it’s there for.

You trace it back using the Item name. If you forget what the “Nighttime” is for, open your .items file and look for it. If you’ve put comments in at least one of the places you will find it. But for the most part, the fact that the Item is named “Nighttime” and is used as a Switch in the Rule should be just about all you need to understand that it’s a Switch that turns on when it is night.

This is one of the reason why I’m a big proponent of using meaningful Item names and why I recommend naming Items independent of the technology they are linked to. “Livingroom_Lamp” is a whole lot more meaningful than “Zwave_Switch7”.

while (door_light.state != OFF) {
}

That looks like an infinite loop to me…

Yes, sir. In fact that’s the “Rule 2” in my setup - thank you for making it available.
The only difference is that I wanted the “time of day” to trigger a scene and not to alter it (like in your irrigation example). It has worked before with some “Thread::sleep”, but it stopped since I deleted all of the sleeps. Hence my question here. I implemented the proposed solution now and have to wait till the night to see if it works.

BTW. in the comments in my .rules file I noted that there was a bug which didn’t permit to trigger a scene by multiple cron entries (at the time of me setting it up). It seems that’s no longer true, so I assume I may update my scene?

I see. I have some “proxy_items” in my setup, which are virtual switches (by virtual I mean they are not connected to any physical equipment or technology, besides openhab).
What I meant actually is the fact, that those switches may be triggered by some rules and they may be updated by some rules, or even by some bindings, like multimedia bindings etc. I still know what the switch does, but I may easily forget where it gets its updates from or what it causes. Comments in files may save the day :wink: so I’ll go with that. (I am actually trying to use it already)

I guess I’m confused then. Why is there more than one Rule that cares about Astro events then? Only the time of day Rule should care about those. Everything else triggers off of or checks the Time of Day Item.

That’s been fixed for awhile now, you can have multiple cron triggers now.

It was because I didn’t know how to trigger a scene on sunset, so I used

Channel 'astro:sun:home:civilDusk#event' triggered START

in the other rule (Rule 1) as well. But I wanted a different reaction for winter than for sommer, so my Rule 1 (triggered as above and by cron) checked whether it’s already night or not, relying on Rule 2 (which wasn’t ready yet). It won’t be needed any more using this “proxy switch” I hope.