Engine "too fast" for looping blocker?

Hi,

as I read this topic:

I just had a look at my own “sync Button” script/rule combination:

Trigger:

configuration: {}
triggers:
  - id: "4"
    configuration:
      groupName: VorkampswegX_OG_bath
    type: core.GroupStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      blockSource: <xml xmlns="https://developers.google.com/blockly/xml"><block
        type="oh_runrule" id="!(.8pu/U-Zgyj_m%YZT5" x="86" y="94"><value
        name="ruleUID"><shadow type="text" id="S-~hVsRgu}^Gs]Y3em,d"><field
        name="TEXT">ruleUID</field></shadow><block type="text"
        id="S-~hVsRgu}^Gs]Y3em,d"><field
        name="TEXT">script_sync_buttons</field></block></value><value
        name="parameters"><block type="dicts_create_with"
        id="jVly/bGQhlJ|!,):ZQ/#"><mutation items="2"></mutation><field
        name="KEY0">sourceButton</field><field
        name="KEY1">targetButton</field><value name="ADD0"><block
        type="oh_context_info" id=",/Z)%nG3u/H~g93Ev@(%"><mutation asType="null"
        contextInfo="itemName"></mutation><field
        name="contextInfo">itemName</field></block></value><value
        name="ADD1"><block type="oh_item" id="A0BEhyuegH,l|v=_d#`j"><mutation
        itemName="VorkampswegX_OG_bath" itemLabel="Hauptbad"></mutation><field
        name="itemName">VorkampswegX_OG_bath</field></block></value></block></value></block></xml>
      type: application/javascript
      script: >
        rules.runRule('script_sync_buttons', {'sourceButton': event.itemName,
        'targetButton': 'VorkampswegX_OG_bath'});
    type: script.ScriptAction

var source, target, allready_in_execution;

var thread = Java.type('java.lang.Thread')


source = ctx['sourceButton'];
target = ctx['targetButton'];
if (!allready_in_execution) {
  allready_in_execution = true;
  items.getItem(target).sendCommand(items.getItem(source).state);
}
thread.sleep(500);
allready_in_execution = false;

Having following LOG:

  • Item ‘ZWave_Node5_Schalter_2’ changed from ON to OFF
    Item ‘VorkampswegX_OG_bath’ received command OFF
    Item ‘ZWave_Node5_Schalter_2’ received command OFF
    Item ‘ZWave_Node4_Schalter_1’ received command OFF
    Item ‘ZWave_Node5_Schalter_2’ predicted to become OFF
    Item ‘ZWave_Node4_Schalter_1’ predicted to become OFF
    Item ‘ZWave_Node4_Schalter_1’ changed from ON to OFF
    Item ‘VorkampswegX_OG_bath’ received command OFF
    Item ‘ZWave_Node5_Schalter_2’ received command OFF
    Item ‘ZWave_Node4_Schalter_1’ received command OFF
    Item ‘ZWave_Node5_Schalter_2’ predicted to become OFF
    Item ‘ZWave_Node4_Schalter_1’ predicted to become OFF

For sure it is working as exspected, but I guess everyone can see the issue that the script is triggerd a second time before the flag can be set for dont do it :wink:

Can it be optimized without changing the generall aproach? (I know all the alternative statements)

Greatings

I don’t think you can make this work. Calling another rule is not a replacement for creating a library. It is great in a few specific use cases but if you are just trying to avoid duplicating some code, particularly some code that is likely to get called from multiple rules at the same time or in rapid succession, you will have problems.

Some issues you might see:

  • Multi-threaded access exceptions: GraalVM only allows one thread to access a context (i.e. a Script Action or Script Condition) at a time. There are locks in place within a single Script Action/Condition to prevent this but there are no locks to prevent this when two rules call the same other rule at the same time. Given this your “lock” isn’t really doing anything. If two calling rules were in that script at the same time it would generate an exception.

  • If you are using other languages which do allow multi-threaded access to the same script, each rule is calling the same script meaning that as one rule is executing the called rule and the second one comes around, the second one could change the values of variables out from under the first one leading to unexpected results. Calling another rule isn’t like a function call.

Because of these issues, the ability to call another rule almost wasn’t allowed or supported at all. Trying to use them in this way is an anti-pattern.

No, and your overall approach is flawed. You should use a library, create a custom Block Library, or put both the caller and the callee rules into the same rule. There are other options as well.