Suppose we have an Event
type that has 3 properties: constraint
, common
, and distinct
. The goal is to write a rule in Drools that fires when a subset of Event
s exists that meets the following criteria:
Event
s happened in the last t seconds; andEvent
s Have a previously known value for constraint
property; andcommon
property; anddistinct
propertyIf the rule fires, we need the set of participating events for further processing.
How do you advise we approach this problem?
Note 1: This question is somewhat similar to link, and Steve's answer there seems promising but is incomplete.
Note 2: Performance is of the essence. We have successfully developed rules that do this task, but they reduce the performance of the whole rule-base dramatically, and thus are unacceptable.
Edit 1: The current (poorly performing) solution looks like this:
rule ""
when
$event : Event(constraint == CONSTANT_VALUE)
$events : ArrayList() from collect(
Event(constraint == CONSTANT_VALUE,
common == $event.common)
over window:time( t ))
$distinctVals : Set( size >= n ) from accumulate(Event($d : distinct) from $events, collectSet($d))
then
// process $events
end
Drools isn't meant to be used for computations that require repeated evaluations of a potentially big set of facts. In such a situation you'll have to offload the details to some Java code.
class Collector {
String constraint;
String common;
List<Event> events = ...; // or Queue
Map<String,List<Event>> dist2events = ...;
int diversity;
public void addEvent( Event e ){
// 1. remove Event sets X from events older than t
// 2. remove all members of X from dist2events,
// delete map elements where the value list is empty
events.add( e );
List<Event> ofDistinct = dist2events.get( e.getDistinct() );
if( ofDistinct == null ){
ofDistinct = new ArrayList<Event>();
dist2events.put( ofDistinct );
}
ofDistinct.add( e );
diversity = dist2events.keySet().size();
}
}
rule createCollector
when
Event( $constraint: constraint, $common: common )
not Collector( constraint == constraint, common == $common )
then
insert( new Collector( $constraint, $common ) );
end
rule addEvent
when
$event: Event( $constraint: constraint, $common: common )
$collector: Collector( constraint == constraint,
common == $common,
events not contains $event )
then
modify( $collector ){ addEvent( $event ) }
end
rule MoreThan
when
Collector( $constraint: constraint, $common: common,
$events: events,
diversity >= n ) // maybe only when n-1 to n?
then
... process $events
end
You'll have to decide whether you want this rule to fire only when the threshold n is exceeded or whenever the set changes while diversity is >= n.
You might want to add a rule to remove empty Collectors.