ReentrantLock with Timer

I have a rule that starts up my generator and that rule uses locks so that other rules in the same file don’t run at the same time and cause issues. I am running into a problem however because it looks like the timer part is outside of the lock.

2016-01-10 18:51:19.889 [INFO ] [g.openhab.model.script.Testing] - Generator Started - Locking
2016-01-10 18:51:20.057 [INFO ] [g.openhab.model.script.Testing] - Generator Started - Unlocked

I expected the lock to hold for 45 seconds, long enough for the generator to start, not less then 1 second.

rule "Generator Started"
when
        Item Generator_Auto received command ON or
        Item Generator_Override received command ON
then
        logInfo("Testing", "Generator Started - Locking")
        lock.lock()
        try {
                sendCommand(Generator_Start, ON)
                generator_start_timer = createTimer(now.plusSeconds(45))
                        [
                                if (Generator_Status.state == CLOSED) {
                                        sendCommand(Generator_Failed, OFF)
                                        sendCommand(Generator_Cooling, OFF)
                                        whenStarted = now // Start Clock
                                        generator_load_timer = createTimer(now.plusSeconds(30))
                                                [
                                                        sendMail("xxxxxxxxxx@mms.att.net", "Generator", "Generator Started, load at " + Buy_Total_Watts.state + " watts")
                                                ]
                                } else {
                                        sendCommand(Generator_Failed, ON)
                                        sendCommand(Generator_Override, OFF)
                                        sendMail("xxxxxxxxxx@mms.att.net", "Generator", "Generator Failed to Start!!")
                                }
                                generator_start_timer = null
                        ]
        }
        finally {
                lock.unlock()
                logInfo("Testing", "Generator Started - Unlocked")
        }
end

A timer runs in a separate thread from the rule that created it once it is created so there is nothing to prevent the rule from exiting immediately.

If you need the lock to remain locked for that time you need to either unlock it as the last thing your timer does (probably not a good idea) or add a Thread::sleep(45000) to the finally just before the lock.unlock().

sorry picking up this old topic.
but with the new behaviour from the below topic I have the exact problem that Ican not use thread sleep and still want a specific rule to sleep for some minutes and not reexecute. as I read here reentrant lock + timer seems not recommended aswell

Use a Latch but instead of using a ReentrantLock, use a timestamp or the Timer itself as the Latch.

For example

val Timer timer = null

rule "Latched rule"
when
    // some event
then
    if(timer == null) {
        timer = createTimer(now.plusSeconds(45), [|
            // stuff to do after timer goes off, can be empty
            timer = null
        ])
        // rule execution logic
    }
end

In the above rule, the rule logic will only execute when there isn’t a timer running. All events that occur while the Timer is running get ignored.

This could also be implemented using an Expire binding timer

Switch MyLatchedTimer { expire="45s,command=OFF" }
rule "Latched rule"
when
    // some event
then
    if(MyLatchedTimer.state == OFF) {
        MyLatchedTimer.sendCommand(ON)
        // rule execution logic
    }
end

rule "Latched rule timer went off"
when
    Item MyLatchedTimer received command OFF
then
    // stuff to do after the Timer goes OFF
end

If this isn’t what you are trying to do please postcode and I can adjust the above example to fit.

Note that in that thread you linked to, it turned out that only Thread::sleeps in System started rules cause other rules to not execute and I think it has been fixed. However, Thread:sleeps longer than 300 should not be used so you will want to deal with the sleep using a Timer anyway.

You only need the ReentrantLock if you want the rule to execute for each and every event, but never at the same time. The above will ignore any events that occur while the Rule is currently running. If you are sleeping for 45 seconds, I suspect ignoring the events is the proper behavior. If not, then you probably need to come up with some other approach.