States as observed by rule body, "transaction isolation" or races

I could nail down some rule so it only trigges for a specific change, like:

rule "rule 1"
when
	Item MyItem changed from A to B
then
    logInfo("test", "state=" + MyItem.state)
end

Or my rule could be less specific, like e.g.:

rule "rule 2"
when
	Item MyItem changed
then
    logInfo("test", "state=" + MyItem.state)
    if (MyItem.state == "B")
    {
      ...
    }
end

Now when there really is a state change from A to B both rules would trigger. But does openHAB assure absolutely that the state of the item under question is the one after the state change, i.e. both log statements would log “state=B”?

I assume we only observe one single change, not 100 fast changes where you allready might see a “future” state of the item because it has undergone other changes in between. Or not? Would the execution of the rule be executed sequentially before other changes? I doubt, as this would not allow changing any state in the rules body.

The OH Event Bus and Rules engine are multi-threaded and there are no checks in place to ensure order of operations or to ensure that an Item’s state does not change while a rule is running.

So in your hypothetical, if the Item is changing fast enough and the timing of the threads occur with just the right timing, MyItem.state can theoretically be the state for a change that happened after the rule started executing.

When you have a rule that triggers by received command, a special variable receivedCommand will be populated with the state of the command that caused the rule to trigger. This variable will be unaffected by the additional commands that come in and change the states of the Items behind the scenes.

Furthermore, realize that each command or change or update will cause a separate instance of a Rule to run. If your Rule takes some time to run you will have multiple instances of the Rule running at the same time so you have to be careful with shared resources. There is access to locks to help with this.

This is one reason why long Thread::sleeps can be problematic.

In a Home Automation context, the likelihood that one will routinely receive commands or updates close enough together that this becomes a problem in practice is very low. But OH is not a real-time system and it does not provide transactions nor guaranteed ordering of processing so if you will be seeing events like this, you may need to handle them externally to OH or come up with something clever to mange the events.

1 Like

Thank you very much for the clarification. Your knowledge has some details in it making me doubt that this is just something you found out after many experiments. So it seems I must have missed something reading the docs. Especially this “recievedCommand” sounds interesting. Still, when I google it, I find some forum threads with it, but nothing like the “definitive guide to rules semantics”. Seems I have to be patient to pick up everything step by step. OTOH I feel like having achieved quite a lot already in two weeks. But always, when I create a new topic in the forum, I ask myself whether I’ve really looked at the docs first.

In fact, I didn’t expect a waterproof transaction isolation. That big word in the headline should just make clear the direction in which I was thinking. Still, my expectation would have been, that in the case of a single “slow” event, the rule body would only be executed after the target state has been reached. With “target state” I mean that circumstance which triggered the rule in the first place. So the body would somehow observe the “after”. But maybe the “receivedCommand” has this knowledge. Is there a similar variable like receivedUpdate?

Disclaimer: I’m always fine with a short pointer to some other relevant doc or post.

That is mostly it. I’m a developer and I’m good and figuring out how things should work based on the behaviors I see and experience I’ve had building similar systems in my past, though the maintainers will tell you I’m often wrong.

But I have been using OH for a long time now myself and I’ve been actively helping people solve problems that arise out of this behavior for almost as long. Almost all of the Design Pattern postings came about as a way to help someone else solve their problem that I simply codified so I can link to it later when the same problem gets asked about again.

This specific behavior with Rules and ordering of operations and such does come up though when one uses a Group received update to trigger a rule because in that case, because of the way a Group’s state is calculated, the rule gets triggered a whole bunch of times for one update to a member of that Group. This is one case where reentrant locks and the understanding the behavior of the event bus and rules is important.

http://docs.openhab.org/configuration/rules-dsl.html#implicit-variables

As with most open source projects, particularly one without corporate backing, the Docs are always in a state of becoming.

Also, there are many important little pieces of information like this which can easily be missed when a qucik scan of the docs because despite their import, there isn’t much to say about them.

I think that is the case because I’m pretty sure (not positive mind you) that the Item state gets updated first and then the fact of that update gets published on the Event Bus from which Persistence and Rules and Bindings pick up the event and act on it.

So while we cannot guarantee that the Item will not have changed state when the Rule starts running, I think we can say that the Item will at least be the most recent state (i.e. the rule will not trigger before the Item reaches the correct state).

Unfortunately not. There is a previousState variable for rules triggered by a change but that is it. What would be super useful is a “triggeringItem” as then we can have Rules with multiple Items as Triggers and not have to use a hack to figure out which Item caused the rule to trigger.