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 newFireAlarm
wheresrc=Home
and certain fieldresponseTime
in the event tells user that whether it's duration is more than100ms
old or not. The rule need to check if it gets5
suchFireAlarm
in1 minute
, it would create aFireAlarmHome
event (which too has a field with nameresponseTime
with the same value ofFireAlarm
event'sresponseTime
field) with an expiry period set to it and also a parallel event namedHealthHazard
needs to be created to track if the alarm is hazardous or not. So now a rule needs to be specifically fired whenFireAlarmHome
expires which would update theHealthHazard
event'sstatus
field 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
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 theconcept 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 stillvalid
/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'sLHS
in such a way that it tries to correlate eachFireAlarmHome
event with it's correspondingHealthHazard
event , 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 imaginaryhealthHazardId
field inHealthHazard
event, just to correlate the associatedFireAlarmHome
event with it's respectivehealthHazardId
event. This would help developers identify whichFireAlarmHome
corresponds tohealthHazardId
event.
- 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.
Comments