Reputation: 171
I am new to Drools. I need to build an application with spring-boot & Drools(7.40.0.Final) where springboot application streams an external source that will continuously trigger data packets (tracking data related to movement of an entity) to my application. I need to use evaluate all these streaming data.
I am using a "geofence_rule.drl" file to keep the rules related to the geographic locations.
rule "Rule for Tag position in room 1"
when
model : ComponentModel(positionValue <= 50)
then
model.setRoomId(1);
end
rule "Rule for Tag position in room 2"
when
model : ComponentModel(positionValue > 50)))
then
model.setRoomId(2);
end
Model class is as below.
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class ComponentModel{
private long tagId;
private long roomId;
private int positionValue;
}
I may get position related data of "n" number of tags say tag1, tag2 tag3 and so on. I need to calculate if tag1 is absent from Room-1 (which means tag-1's data does not hit "Rule for Tag position in room 1") for Last 5 minutes. Is there any support in Drools for such calculation?
I have seen "not" keyword in drools documentation. But it just negating the condition of Rule. I need to check rule hiting nature for last few minutes, this time limit is configurable in application.
Upvotes: 0
Views: 400
Reputation: 15179
You're looking for stream mode and negative patterns. The links are to the official Drools documentation.
Stream mode is one of two event modes in Drools. The default is "cloud" mode, where you have all of the facts up front and it makes decisions automatically. The other mode, "stream" mode, is intended for processing temporal streams, which sounds a lot like your "pinging" application. In stream mode, Drools evaluates each fact as it comes in, and is aware of time -- namely when other facts were in.
Negative patterns in stream mode are the logical temporal extension of the not
keyword. As you correctly pointed out, in cloud mode it simply negates a condition (eg. "there is no condition in working memory that matches this criteria.") In stream mode, however, you can update these patterns to take effect over a period of time.
The Drools documentation provides this example:
rule "Sound the alarm"
when
$h: Heartbeat() from entry-point "MonitoringStream"
not(Heartbeat(this != $h, this after[0s,10s] $h) from entry-point "MonitoringStream")
then
// Sound the alarm.
end
The first line in the 'when' clause identifies an instance of a heartbeat ($h
). The second identifies the situation when a heartbeat is not received within 10 seconds. If both conditions are true, the rule is executed -- in this case an alarm is triggered.
This is the same pattern you'd apply for your rule.
rule "Tag has not been in Room 1 for 5 minutes"
when
// Tag with ID 1, present in Room 1 -- First instance
$tag: ComponentModel( tagId == 1, roomId == 1 ) from entry-point "TrackingStream"
// Trigger if this condition hasn't been met a second time within 5 minutes
not( ComponentModel(
this != $tag,
tagId == 1,
roomId == 1,
this after[0s, 5m] $tag ) from entry-point "TrackingStream")
then
// Do whatever it is you need to do for this condition
end
In this case, I'm leveraging the after
temporal operator (link to Drools documentation.)
Basically this is how it works--
$tag: ComponentModel( tagId == 1, roomId == 1 ) from entry-point "TrackingStream"
The first condition identifies the scenario, in this case ID 1 is present in Room 1. It identifies the current instance of that situation we're tracking. Since this is a temporal stream, it's easy to think of it as "Tagged entity (1) has just entered Room 1."
not( ComponentModel(
this != $tag,
tagId == 1,
roomId == 1,
this after[0s, 5m] $tag
) from entry-point "TrackingStream")
This is where the magic happens, and the syntax takes a bit getting used to. This second condition is waiting for the next temporal and then checking the conditions. The conditions checked are:
The temporal constraint (this after[0s, 5m] $tag
) says to wait to check this condition. If a second ComponentModel is received within this time-frame after $tag
, then the rule will not trip, and the scenario will repeat waiting for up to another 5 minutes. Since the time range [0s, 5m]
starts checking immediately, we need to exclude $tag
explicitly from the matching in the not(...)
clause (this != $tag
.)
To illustrate, this is how it might execute (simplified):
$tag
= Event A. We begin checking incoming streams for the second condition.$tag
= Event C.Upvotes: 2