How to fire rules when an event expires?

Solution Verified - Updated -

Environment

  • Red Hat JBoss BRMS (BRMS)
    • 6.x

Issue

  • Is there a way to design a rule in such a way that it fires when events expire?
    e.g.
declare  FireAlarmHome
      @expire(1m)
end

For an example as the event AlarmEvent expires, it should fire all rules.

  • For an example of a fire alarm (FireAlarm) coming in to the working memory. So users get a new FireAlarm where src=Home and certain field responseTime in the event tells user that whether it's duration is more than 100ms old or not. The rule need to check if it gets 5 such FireAlarm in 1 minute, it would create a FireAlarmHome event (which too has a field with name responseTime with the same value of FireAlarm event's responseTime field) with an expiry period set to it and also a parallel event named HealthHazard needs to be created to track if the alarm is hazardous or not. So now a rule needs to be specifically fired when FireAlarmHome expires which would update the HealthHazard event's status field to green , marking it to be safe now. How to implement it?

Resolution

  • The proper way to achieve this requirement is to do it with a simple negative rule. e.g:
 rule "System is healthy"
    duration(1m)
 when
    // when no FireAlarmHome event is there with response time over 100ms in the last minute
    not( FireAlarmHome ( src=="Home", responseTime > 100 ) )
 then
    // update HealthHazard's 'status' to green
 end
 Rule above is just an example. There are other ways of doing this, like if users want to count events, they can use a sliding window, etc.
  • The aforementioned suggestion can be effective but it has a limitation, that it won't be effective if there are multiple FireAlarmHome events roaming actively in the working memory. In order to overcome such difficulty here are some thoughts and alterations done to the previous proposal.
    • First try to understand the concept and semantic of event expiration. Imagine that it was possible for a machine to have infinite memory and infinite computing power. On such hypothetical machine, no event would ever expire. They would just remain in memory forever and this would not affect such machine performance (as it has infinite resources). The problem is, of course, that such machine does not exist, and to save resources the concept of expiration was created. An event will expire (and hence will be removed from the working memory) when it is no longer necessary to match any rules. Do note that the event is still valid/true , just no longer useful.
      • Now, considering a situation where there are the occurrence of multiple FireAlarmHome events roaming actively in the working memory then in order to meet such requirement rule developers would need to modify the previously suggested rule's LHS in such a way that it tries to correlate each FireAlarmHome event with it's corresponding HealthHazard event , which got generated at the same time as FireAlarmHome . It might look something like this. Do note that for a demonstration purpose only the it has been imagined that there is an imaginary healthHazardId field in HealthHazard event, just to correlate the associated FireAlarmHome event with it's respective healthHazardId event. This would help developers identify which FireAlarmHome corresponds to healthHazardId event.
rule "Home is healthy and expired FireAlarmHome"
when
    $healthEvent: HealthHazard ($id: healthHazardId)
    // when no alarm with response time over 100ms in the last minute which contains referenced "healthHazardId"
    not( FireAlarmHome( src=="Home", responseTime > 100 , healthHazardId == $id, this after[0,1m] $healthEvent ) )
then
    // update HealthHazard's 'status' to green
end

N.B. Interesting thing to note with the aforementioned condition is that the use of a temporal constraint this after[0,1m] $healthEvent to the LHS in addition to the non-temporal condition healthHazardId == $id , which users might think being adequate to validate whether the FireAlarmHome event belongs to the same HealthHazard event object or not. It's significance is that, as soon as developers add a non-temporal constrain (like "healthHazardId == $id" in the above example) without other temporal constraints between the same events, they are basically telling the engine that those events involved are useful forever and will never expire (unless developers explicitly override their expiration offset). Hence, the following temporal constraint is necessary because it implicitly defines for how long an event is useful (e.g: $eventA after[0,1m] $eventB means that $eventB is useful for 1 minute).

Of course, this example assumes that the engine is running in STREAM processing mode and both FireAlarmHome and HealthHazard are declared as events.

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments