I am trying to debug a set of rules that control a thermostat and I need to understand how the nesting of "run rule actions" works. Assume I have three rules (A, B, C). I run rule "A" and in the middle of its execution it says to run the rule actions of Rule "B". In the middle of rule "B" a command is issued to run the actions of Rule "C". When "C" finishes will rule "B" resume, and will rule "A" resume when rule "B" finishes?
Also, what about hub variables? If rule "A" changes a variable will the actions of rule "B" see the change when it starts? Thanks. I have looked for a clear answer to these questions elsewhere on the forum but don't seem to find them.
I don't believe you can think of rules as subroutines or even that it is a programming language. We know there is no lock mechanism between rules that keep them from walking over themselves, That suggests they are concurrent processes started in response to triggers. Ensuring a seq of A-calls->B- calls->C-> returns to B->return-to->A would be nearly impossible and undesirable.
Yes, this is basically how it works. Running a rule happens as a method call on the parent app, that in turn makes a method call on the rule to be run. The called rule does its thing, and returns from the method call from the parent, which in turn returns to the original rule. Etc.
Wehn a rule changes the value of a Hub Variable, that happens immediately, so if this happens prior to running a rule, the rule that is run will see the changed value.
A rule also passes to the rule that is run its last event value, device name, and event time/date, which would have come from whatever triggered it.
Ordinarily this will in fact work as described, and there is no reason for it to be considered 'undesirable'.
This calling of a rule by another has nothing to do with a rule being triggered. A trigger event is asynchronous; that is, it can happen at any time, including while a rule is already 'running'. This can lead to simultaneous multiple instances of a rule running, which generally is not a good thing unless anticipated and properly managed. However, a rule running the actions of another rule is a sequential event, much like calling a subroutine or method in a programming language; it is not asynchronous. However, this assumes that there are not multiple simultaneous instances of this taking place.
A rule can easily be setup so that it has no triggers, only actions. Such a rule can be run by another rule, and it acts exactly like a subroutine (no triggers to mess things up).
Yes I have rules with only actions and treats them as sub-routines (actually I call them functions) but I had no idea that the paused the calling rule. I just assumed they ran concurrently. In some cases I have run commands followed by a wait for event statement waiting for the called rule to finish. I guess I can remove the waits.
I misunderstood how this worked as well. I always thought of run another rule as just another way to trigger it. I did not realize the calling rule stopped(waited). I will have to make a test case and watch this.
I have a few rules that call others but mine are all the last line of the rule. I mostly use this, as Bravnel suggested, to have rules that do not have other external triggers to "mess things up." If the calling rule halts, then I might can rethink how I do new rules going forward.
My testing of this shows that what Bravnel said is true as long as the called rule does not have any waits or delays in it.
It's a bit more subtle and complex. First of all, the writeup above only applies to Rule Machine rules running another Rule Machine rule. It works differently for a Rule Machine rule to run a Rule Machine Legacy rule, or for a Button Rule to run another rule (see below).
Second, and more importantly, when a rule runs having been called by another rule, it is running the same CPU thread. Once it exits, that thread returns just as with a method call (A calls B calls C, C returns, B returns, A continues). It is important to note that "once it exits" means the first to occur of finishing its actions, or entering a delay, repeat or wait. In the case of delay, repeat or wait, the called rule exits, so the thread returns to the caller. When the delay, repeat or wait is over, a new thread is instantiated to continue running the called rule. So in this case, there could be simultaneous execution occurring. This is true generally of delay, repeat and wait, so this is nothing new. Be careful what one means by A -> B -> C -> B -> A in this regard.
Careful here, It is no more "waiting" than code "waits" when a method (subroutine) is called. Execution of code passes to the method code, and when the method returns the execution continues beyond where the method is called, all within a single continuous computational thread of execution.
In the case where a Rule Machine rule runs a Rule Machine Legacy rule, or a Button Rule runs a rule, this is done by an event being sent to the relevant parent app. So this case acts more like a trigger, where execution of the rule does continue immediately (in the same thread), and a new thread is created for the called rule.
I believe I demonstrated that for myself, for what it's worth. I used Pushover to send a message from rule "A". Then I used Pushover in rule "B" using a Repeat function. The cycle was 3 times in 15 seconds. Finally I had Rule "A" send a second message.
The messages that arrived in Pushover went A1, B1, A2, B2, B2. I tried it multiple ways, changing wait times. Same result exactly. It appears using the Repeat function does interrupted the order of things. I wish that weren't the case, because it means multiple threads are running and I was trying to conserve them.
I should have read @bravenel's comment above more carefully.
There is no need to "conserve" threads. You just need to be aware of how things are sequenced in time. Each of these rules occupies a thread for a very short time before it exits, waiting for the next scheduled event or trigger event, etc.