Design question - cron versus rule for periodically triggered events

What I’ve learned by browsing the posts here:
maximum parallel cron jobs: 2
maximum parallel rules: 5

I have a question about how to solve these problem:

What I have:
I run a cron job once a day to check something and do something. To prevent me from influnce of other rules/crons I want to choose the right way to implement this.

Current implemenation:

rule "Daily midnight job"
	when
		Time cron "0 9 0 * * ?"
	then
           callScript("holidays")

           if(!gBatterieLevelNU.allMembers.filter[ battery | (battery.state as Number) <= (nuBatteryLowErrorLevel.state as Number) ].empty)
           {
             some commands
           }

           ... more of this group loops for other checkings
end

This cron rule will run maybe for some minutes. It belongs to the amount of checking loops. If there will be another cron job it can be blocked by this long running one.

I can change this logic to this one:

rule "Daily midnight job"
	when
		Time cron "0 9 0 * * ?"
	then
              TriggerBatterieLevelNU.postupdate(ON)
              Trigger SomeOtherRules .postupdate(ON)
end

And outsource the real doing to rules

rule "TriggerBatterieLevelNU"
	when
		Item TriggerBatterieLevelNU changed to ON
	then
           if(!gBatterieLevelNU.allMembers.filter[ battery | (battery.state as Number) <= (nuBatteryLowErrorLevel.state as Number) ].empty)
           {
             some commands
           }
           TriggerBatterieLevelNU.postupdate(OFF)
end

and so on for the other checking rules.

With this the cron job ends very fast and only the rules are run for a while in parallel. But then it could be, that I trigger more then 5 rules in parallel.

At the end I run into the same problem, that my rules/cron jobs could block each other for the checking period of time.

You can say, hey, use for every check a cron with is 5min. after the earlier one to do checking in cascade. But this is not very good looking code and in some years no one will understand what is going on :wink:

Any help is welcome.

I don’t understand why you’re saying that.
You can run the same or different rules multiple times in parallel, started at the same time from cron.
They won’t block each other unless you program them to be dependent on each other (but to query items or to send commands doesn’t block a rule).
Ok you eventually need to increase the number of threads available for rules in config, but that should be about it…

Why is that a problem for you? Things happening a few milliseconds after each other aren’t necessarily an issue.

Blocking only occurs if you have written rules that hang around in some way.

Almost related - general advice for “midnight job”, make it a few minutes after midnight so that you’re not competing with e.g. system tasks like backup.

This is why I use

Time cron "0 9 0 * * ?"

9min. after midnight.

If I configure in another rule a cron job with the same settings " Time cron “0 9 0 * * ?”. No problems because 2 of them can run at the same time. But if I configure three of same by mistake, the third one will not run.

At the moment I have a list of existing cron jobs and when they run to prevent me from doing this.

Here is my real example of what I do at the moment in the cron job

every day at 22:00 o’clock

  • check if all windows are closed
  • check if trash bin must be put out at street
  • all doors are locked
  • all radiators are off
  • all roller shutters are down

This all will take some time and I will stay in the cron rule.

Try

org.eclipse.smarthome.threadpool:RuleEngine=5 (or larger)

in runtime.cfg

Oh yes … must put my spectacles on !

The limitation about multiple cron triggers at the same time is not unreasonable … they could never actually trigger all at the exact
same time, and someone would complain about that too.

That isn’t a problem (so long as it does eventually complete). It’s only one rule running. only takes one thread, and allows multiple e.g. motion triggers, switches, etc. to happen alongside.

From a developers ease of maintenance point of view, it would make sense to split the rule into e.g. door/windows action rule, dustbin check rule. I wouldn’t hesitate to do that either.
The key thing is so long as your rules complete nothing gets blocked.

For myself I do this stuff on the “time of day” model - that handles the crons, and I have multiple rules triggered off a state change to do the chores.

Thanks for the feedback. I know this and use this at the moment too.

I just want to know, if there is a best practice outside here how others do this.

To increase the thread pool is best practice.
Anything else would require to be applied to the code so it would be a user- or application-specific solution and as such not applicable in general.
Then again, it’s also best practice to avoid any long-running rule, so try optimizing those as well.

perfect, I will do my tuning that way. Thanks.

Note that this was changed in the latest ESH stable release (change number 12 in build 300). It’s now ruleEngine instead of RuleEngine.

1 Like

Thanks for pointing out.
By chance I got bitten by that Karaf auth disaster in #1386 so “luckily” I’m not there yet…

I take an opposite view and have never tinkered with thread limits :wink:
It probably helps I’m running a relatively powerful (old laptop) host and not a Pi, but the way I see it - if you’ve got X amount of processing to do, it matters little whether you do it in parallel chunks or serially.
So long as the host is multi-thread capable, other tasks will remain more responsive if housekeeping is confined to one thread.

I have several cron rules, none of them take a long time to execute.
But for the daily ones around midnight, I stagger them one every minute or so, so as to avoid conflict.
Be aware that the astro binding will recalculate the daily triggers at 30 seconds past midnight.

So people need to change their runtime.cfg for this to work in the future.
@Benjy, there’s a fairly new “feature” of the oh-distro install scripts(?) to display breaking changes on package install, is that under your control ? If so please add this one, if no do you know where to properly address this instead ?

I try to keep an eye out for breaking changes but anyone can make changes to the list. This probably went unnoticed as it’s marked as an API breaking change from the ESH repository only.

Only editing this file is needed, I can submit a PR if you wish but you are welcome to get there before me! :slight_smile:

Do you know this or do you assume this?

Nothing you list here should take more than few hundred milliseconds in total unless you are adding significant Thread::sleeps or calls to executeCommandLine or calls to sendHttp*Requests.

If you are just doing filters and loops on Groups this Rule should take much less than a second to run unless you are on a significantly underpowered machine like a RPi 1, even if your … bullet point is twice as long as the five preceding points.

To directly answer your question though, best practice is to avoid having your Rule sit around doing nothing but waiting.

If you do have loops with sleeps in them it would be better to replace the loops and sleeps with looping timers so you are not tying up any threads doing nothing.

As a slightly different way to answer this question, I wonder if you even need to do these checks at a certain time. It obviously depends on your rules implementation, which you didn’t really share much of.

For example, I would prefer the battery portion of the rule that you did share as an item or group based trigger. If you set the group of battery items to be a minimum type group them the value of the group will show the value of the battery item with the lowest value in the group. Trigger on group change and the rule will be triggered in real time if any items battery drops too low. Similar things could possibly be done with other portions of the rule too.