Drools: get the 3 most recent Events

前端 未结 2 1855
自闭症患者
自闭症患者 2020-12-20 23:10

I\'m working on a small Drools project, because I want to learn more about using rule engines. I have a class called Event that has the following fields:

<
相关标签:
2条回答
  • 2020-12-20 23:46

    Assuming you are using the STREAM event processing mode and your events are ordered in the stream:

    rule "3 most recent events"
    when
        accumulate( $e : Event( tag == "OK" ) over window:length(3),
                    $events : collectList( $e ) )
    then
        // $events is a list that contains your 3 most recent 
        // events by insertion order
    end
    

    ===== edit ====

    Based on your comment bellow, here is how to achieve what you want in Drools 5.4+:

    declare window LastEvents
        Event() over window:length(3)
    end
    
    rule "OK events among the last 3 events"
    when
        accumulate( $e : Event( tag == "OK" ) from window LastEvents,
                    $events : collectList( $e ) )
    then
        // $events is a list that contains the OK events among the last 3 
        // events by insertion order
    end
    

    Just double check the syntax as I am doing this by heart, but it should be close to this.

    0 讨论(0)
  • 2020-12-20 23:51

    I was able to simplify 'not logic' like this

    rule "Three most recent events tagged with 'OK'"
    when
        $e1 : Event( tag == "OK")
        $e2 : Event( tag == "OK", millis < $e1.millis )
        $e3 : Event( tag == "OK", millis < $e2.millis )
        not Event( this != $e2, tag == "OK", $e3.millis < millis, millis < $e1.millis )
    then
        System.out.printf("%s - %s - %s%n", $e1, $e2, $e3);
    end
    

    There was nothing said about cleaning events. Usually this is desirable, so you can achieve the same logic with deletion of the last event:

    rule "Three most recent events tagged with 'OK'"
    when
        $e1 : Event( tag == "OK")
        $e2 : Event( tag == "OK", millis < $e1.millis )
        $e3 : Event( tag == "OK", millis < $e2.millis )
    then
        System.out.printf("%s - %s - %s%n", $e1, $e2, $e3);
        retract ($e3)
    end
    

    Let say each second you'll insert an event one 'OK' another empty '', here is the test:

    @DroolsSession("classpath:/test3.drl")
    public class PlaygroundTest {
        
        @Rule
        public DroolsAssert drools = new DroolsAssert();
        
        @Test
        public void testIt() {
            for (int i = 0; i < 10; i++) {
                drools.advanceTime(1, SECONDS);
                drools.insertAndFire(new Event(i % 2 == 0 ? "OK" : "", i));
            }
        }
    }
    

    all three variants will produce the same triggering logic:

    00:00:01 --> inserted: Event[tag=OK,millis=0]
    00:00:01 --> fireAllRules
    00:00:02 --> inserted: Event[tag=,millis=1]
    00:00:02 --> fireAllRules
    00:00:03 --> inserted: Event[tag=OK,millis=2]
    00:00:03 --> fireAllRules
    00:00:04 --> inserted: Event[tag=,millis=3]
    00:00:04 --> fireAllRules
    00:00:05 --> inserted: Event[tag=OK,millis=4]
    00:00:05 --> fireAllRules
    00:00:05 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [Event, Event, Event]
    OK4 - OK2 - OK0
    00:00:06 --> inserted: Event[tag=,millis=5]
    00:00:06 --> fireAllRules
    00:00:07 --> inserted: Event[tag=OK,millis=6]
    00:00:07 --> fireAllRules
    00:00:07 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [Event, Event, Event]
    OK6 - OK4 - OK2
    00:00:08 --> inserted: Event[tag=,millis=7]
    00:00:08 --> fireAllRules
    00:00:09 --> inserted: Event[tag=OK,millis=8]
    00:00:09 --> fireAllRules
    00:00:09 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [Event, Event, Event]
    OK8 - OK6 - OK4
    00:00:10 --> inserted: Event[tag=,millis=9]
    00:00:10 --> fireAllRules
    

    variant with window:length(3) will also deal with last 3 OK events. It is different on the beginning though: it will be triggered for 1 and 2 first OK events too. It will be also triggered once with empty list on the beginning if session doesn't contain any events. According to documentation, sliding windows start to match immediately and defining a sliding window does not imply that the rule has to wait for the sliding window to be "full" in order to match. For instance, a rule that calculates the average of an event property on a window:length(10) will start calculating the average immediately, and it will start at 0 (zero) for no-events, and will update the average as events arrive one by one.

    00:00:01 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
    []
    00:00:01 --> inserted: Event[tag=OK,millis=0]
    00:00:01 --> fireAllRules
    00:00:01 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
    [OK0]
    00:00:02 --> inserted: Event[tag=,millis=1]
    00:00:02 --> fireAllRules
    00:00:03 --> inserted: Event[tag=OK,millis=2]
    00:00:03 --> fireAllRules
    00:00:03 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
    [OK0, OK2]
    00:00:04 --> inserted: Event[tag=,millis=3]
    00:00:04 --> fireAllRules
    00:00:05 --> inserted: Event[tag=OK,millis=4]
    00:00:05 --> fireAllRules
    00:00:05 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
    [OK0, OK2, OK4]
    00:00:06 --> inserted: Event[tag=,millis=5]
    00:00:06 --> fireAllRules
    00:00:07 --> inserted: Event[tag=OK,millis=6]
    00:00:07 --> fireAllRules
    00:00:07 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
    [OK2, OK4, OK6]
    00:00:08 --> inserted: Event[tag=,millis=7]
    00:00:08 --> fireAllRules
    00:00:09 --> inserted: Event[tag=OK,millis=8]
    00:00:09 --> fireAllRules
    00:00:09 <-- 'Three most recent events tagged with 'OK'' has been activated by the tuple [InitialFactImpl, UnmodifiableRandomAccessList]
    [OK4, OK6, OK8]
    00:00:10 --> inserted: Event[tag=,millis=9]
    00:00:10 --> fireAllRules
    
    0 讨论(0)
提交回复
热议问题