How to fire rules when an event expires?
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 newFireAlarmwheresrc=Homeand certain fieldresponseTimein the event tells user that whether it's duration is more than100msold or not. The rule need to check if it gets5suchFireAlarmin1 minute, it would create aFireAlarmHomeevent (which too has a field with nameresponseTimewith the same value ofFireAlarmevent'sresponseTimefield) with an expiry period set to it and also a parallel event namedHealthHazardneeds to be created to track if the alarm is hazardous or not. So now a rule needs to be specifically fired whenFireAlarmHomeexpires which would update theHealthHazardevent'sstatusfield togreen, 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
negativerule. 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
FireAlarmHomeevents 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 theconcept of expirationwas 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 stillvalid/true, just no longer useful.- Now, considering a situation where there are the occurrence of multiple
FireAlarmHomeevents roaming actively in the working memory then in order to meet such requirement rule developers would need to modify the previously suggested rule'sLHSin such a way that it tries to correlate eachFireAlarmHomeevent with it's correspondingHealthHazardevent , which got generated at the same time asFireAlarmHome. It might look something like this. Do note that for a demonstration purpose only the it has been imagined that there is an imaginaryhealthHazardIdfield inHealthHazardevent, just to correlate the associatedFireAlarmHomeevent with it's respectivehealthHazardIdevent. This would help developers identify whichFireAlarmHomecorresponds tohealthHazardIdevent.
- Now, considering a situation where there are the occurrence of multiple
- First try to understand the concept and semantic of
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.
Welcome! Check out the Getting Started with Red Hat page for quick tours and guides for common tasks.
