When /why should I use "cache"

I am just playing around using JS scripting to get some experiences.
I am not quit clear when / why I should use the “cache” function to store values of variables for the next rule run.

I tried the following rule and get the expected results due to a conditional declaration of the variables. Is it bad practice to do so or what is the advantage of “cache” function?

if (number == null){
  var number = 0;
  var timearray=[];

  if (number >0  &&  timearray[number-1].isActive() ) {
    console.log(`Timer ${number-1} erased  ${timearray[number-1]}`);
  newtime = setTimeout (() => { console.log(`result of number ${number-1}` ); }, 10000);
  timearray[number] = newtime; 
  console.log(`new Timer is ${timearray[number]}`);
  number = ++number;

the result after three runs within 10 seconds is

2022-10-21 10:07:57.740 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - new Timer is org.openhab.core.model.script.internal.actions.TimerImpl@1359756

2022-10-21 10:08:01.585 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - Timer 0 erased  org.openhab.core.model.script.internal.actions.TimerImpl@1359756

2022-10-21 10:08:01.589 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - new Timer is org.openhab.core.model.script.internal.actions.TimerImpl@1841f36

2022-10-21 10:08:04.105 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - Timer 1 erased  org.openhab.core.model.script.internal.actions.TimerImpl@1841f36

2022-10-21 10:08:04.108 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - new Timer is org.openhab.core.model.script.internal.actions.TimerImpl@1e9e4e5

2022-10-21 10:08:05.781 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - Timer 2 erased  org.openhab.core.model.script.internal.actions.TimerImpl@1e9e4e5

2022-10-21 10:08:05.786 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - new Timer is org.openhab.core.model.script.internal.actions.TimerImpl@c6be40

2022-10-21 10:08:15.789 [INFO ] [ript.ui.JavaScriptTestGlobalVariable] - result of number 3

You would use cache in two circumstances:

  1. to preserve a variable between runs of a rule, such as a handle on a Timer so you can reschedule or cancel it.

  2. to share variables between different rules.

cache is much more important when working with rules in the UI as opposed to files, where you have alternative options to achieve these (e.g. declaring a variable outside the rules).

In some cases the variable in the cache will survive a reloading of the rule and the ability to share variables between script actions and script conditions are the two main advantages. Also, the ability to conditionally declare variables is not guaranteed to work forever. There may come a point where the rule is recreated each time it’s run (which will enable us to use let and const and solve a couple of other problems). Right not this only works because the rule script is reused each time the rule is called instead of being recreated.

Thank‘s Rich, that‘s what I thought about the future, killing my project. What I couldn‘d find is, how you can transfer the name or pointer of the cached variable from one rule to another one?

I’m not sure I understand the question. When you use cache it’s giving you access to a HashMap that lives inside the JS Scripting add-on. A may is key/value pairs. So if you use the same key in to rules, you’ll get the same value.

There are limitations though so it’s best to avoid using the cache unless you can’t figure out another way. If you put JavaScript stuff into the cache (as opposed to Java Objects) you’ll get Context is closed errors if you reload the rule that put it there. And two rules cannot access the same value at the same time or you’ll get a multithreaded access is not allowed exception.

There is a PR created to establish an openHAB wide variable registry to do this job across all the supported rule languages. But I think it’s stalled for some reason and am not sure when/if it will become merged.