triggeringItem problem (concurrency?)

Some things I notice.

  • You don’t need to get minutes inside the timer again. You already have it because the timer will inherit everything that exists in the context up to the point where the timer’s lambda was created. That’s why you can access triggeringItem inside the Timer. When you call minutes.state a Number it goes out to the Item registry so you will get the current value.

  • I think this whole Rule would be simpler using Design Pattern: Expire Binding Based Timers.

  • I’ve never seen a doCopyInto error before but it is coming from an UnboundTypeReference. Perhaps if you specify the types of everything inside the Rule that will fix it or give us an error that is easier to figure out.

  • What of those variables does it make sense would become 255?

  • I think the two exceptions are really the same error.

What is supposed to happen is what you would expect. Two separate instances of the Rules get triggered and create two separate Timers. But I gotta say, it’s really hard to get two things to happen in a computer at exactly the same time. I find it highly unlikely that it’s physically possible for you to open two windows and/or have that event get reported to openHAB within the same millisecond. There should be at least a couple of milliseconds between the two just because of noise on the network and in the processor. The fact that the two log statements happen at exactly the same millisecond is suspicious to me.

I imagine it might be possible that Quartz can’t handle two new Timers being created at the exact same time from two different threads. That could cause some problems, but I wouldn’t expect that the two Timers could work at all, meaning that the two log statements wouldn’t have been printed.

I think there are two ways you can go about this.

  1. Preserveer debugging the problem to figure out what is happening, why, and how to work around it.

  2. Pivot and use an alternative implementation (Exipire binding timers) which will not have this same problem.

Interesting thought. I remembered incorrectly. HashMap is indeed not thread safe. I think you can use newConcurrentHashMap to get a thread safe version. If not, the link shows how to create a new ConcurrentHashMap.

But I don’t think that explains the error. If that were the case, I would expect some Timers to not appear in the HashMap when they should (e.g. get null back in the else clause) but it shouldn’t impact the actual running of the Timer’s lambda.

That is true. If you are trying to loop over or filter on a Group and the Group changes it will generate an error. But I can’t remember if it’s just a null error or something else. You can prove this is the case I think by adding a short Thread::sleep between the findFirst and the minutes.postUpdate (maybe 50 msec should do it), but like I said above, the findFirst inside the Timer lambda is unnecessary. So maybe all you need to do is eliminate that line so the Timer uses minutes that was retrieved in the Rule body.