Reputation: 51
I am using the following rule to fire an alert in case there is 1 green packet sent followed by a red packet
package com.myspace.floodmonitoringrules;
import java.lang.Number;
import java.util.ArrayList;
rule "rule3"
dialect "mvel"
enabled true
when
w : ArrayList( size() == 1 ) from collect ( devicestatus( flood_status_color == "green" ) over window:length (1))
ds : devicestatus( flood_status_color == "red" )
then
ds.setFlood_alert( "WindowDetected" );
end
However the rule is getting fired after sending any red packet wven if no green packets sent before. This is when i define ksession as statful. AND when i define it as stateless the rule is not getting fired at all!
i need to understand the behavior as i am new to drools.
Upvotes: 1
Views: 238
Reputation: 51
I added retract( $g ); to your code then it is working perfectly now.
rule "rule3"
dialect "mvel"
enabled true
when
$list : List() from collect (Status() over window:length (2))
$g : Status( floodStatusColor == "green" ) from $list
$r : Status( floodStatusColor == "red", this after $g ) from $list
then
System.out.println("WindowDetected")
retract( $g );
end
Upvotes: 0
Reputation: 20976
This should fit your requirenments
declare Status @role (event) end
rule "rule3"
dialect "mvel"
enabled true
when
$list : List() from collect (Status() over window:length (2))
$g : Status( floodStatusColor == "green" ) from $list
$r : Status( floodStatusColor == "red", this after $g ) from $list
then
System.out.println("WindowDetected")
end
test
@DroolsSession("test.drl")
public class PlaygroundTest {
@Rule
public DroolsAssert drools = new DroolsAssert();
@Test
public void testIt() {
drools.insertAndFire(new Status("red"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("green"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("green"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("red"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("green"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("red"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("red"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("red"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("green"));
drools.advanceTime(1, SECONDS);
drools.insertAndFire(new Status("red"));
}
output
00:00:00 --> inserted: Status[floodStatusColor=red]
00:00:00 --> fireAllRules
00:00:01 --> inserted: Status[floodStatusColor=green]
00:00:01 --> fireAllRules
00:00:02 --> inserted: Status[floodStatusColor=green]
00:00:02 --> fireAllRules
00:00:03 --> inserted: Status[floodStatusColor=red]
00:00:03 --> fireAllRules
00:00:03 <-- 'rule3' has been activated by the tuple [InitialFactImpl, ArrayList, Status, Status]
WindowDetected
00:00:04 --> inserted: Status[floodStatusColor=green]
00:00:04 --> fireAllRules
00:00:05 --> inserted: Status[floodStatusColor=red]
00:00:05 --> fireAllRules
00:00:05 <-- 'rule3' has been activated by the tuple [InitialFactImpl, ArrayList, Status, Status]
WindowDetected
00:00:06 --> inserted: Status[floodStatusColor=red]
00:00:06 --> fireAllRules
00:00:07 --> inserted: Status[floodStatusColor=red]
00:00:07 --> fireAllRules
00:00:08 --> inserted: Status[floodStatusColor=green]
00:00:08 --> fireAllRules
00:00:09 --> inserted: Status[floodStatusColor=red]
00:00:09 --> fireAllRules
00:00:09 <-- 'rule3' has been activated by the tuple [InitialFactImpl, ArrayList, Status, Status]
WindowDetected
You may want to look at similar question, more complicated and interesting.
alternative solution without sliding windows if you do not need older events for other rules
rule "rule3"
when
$g : Status( floodStatusColor == "green" )
$r : Status( floodStatusColor == "red", this after $g )
then
System.out.println("WindowDetected");
end
rule "rule3 cleanup"
salience -1
when
$e : Status()
Status( this after $e )
then
delete($e);
end
Upvotes: 1