mahmoud alorfaly
mahmoud alorfaly

Reputation: 51

Drools Window length and from behaviour

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

Answers (2)

mahmoud alorfaly
mahmoud alorfaly

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

Mykhaylo Adamovych
Mykhaylo Adamovych

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

Related Questions