Drools 6.5 Pseudo Clock

时间:2017-03-28 09:28:26

标签: drools drools-fusion

我在使用伪时钟运行Drools时遇到一些困难。 我在流模式下配置我的引擎,并选择我通过realMode属性使用的时钟类型。

    Date refDate = new Date(System.currentTimeMillis());
    boolean realMode = false;
    SessionPseudoClock clock = null;

    KieServices ks = KieServices.Factory.get();

    KieSessionConfiguration config = KieServices.Factory.get().newKieSessionConfiguration();
    if(realMode) {
        config.setOption( ClockTypeOption.get("realtime") );                        
    } else {
        config.setOption( ClockTypeOption.get("pseudo") );  
    }

    KieContainer kc = ks.getKieClasspathContainer();
    KieSession ksession = kc.newKieSession("cep-rules",config);
    KieRuntimeLogger logger = ks.getLoggers().newFileLogger( ksession, "./out/helloworld" );

    addNewLogLine (ksession, "GDE" , 0);
    addNewLogLine (ksession, "GDE" , 11);
    addNewLogLine (ksession, "GDE" , 3);
    addNewLogLine (ksession, "GDE" , 8);

    logger.close();

    ksession.dispose();

AddNewLogLine函数的代码

    if( realMode) {
        try {
            Thread.sleep(delaiInSeconds*1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }           
    } else {
        if (clock==null) {
            clock = ksession.getSessionClock();
        }
        clock.advanceTime( delaiInSeconds, TimeUnit.SECONDS );
    }
    delai += delaiInSeconds;

    LogItem logLine = new LogItem();
    logLine.setEventDate(new Date (refDate.getTime()+(delai*1000)));
    logLine.setMessage("Message number " + count);
    logLine.setSourceSystemName(sourceSystemName);

    System.out.println(logLine);
    ksession.insert( logLine );

    ksession.fireAllRules();

我给appart留下一些与我的问题无关的额外代码。

规则:

    declare LogItem
        @role (event)
        @timestamp( eventDate )
    end

    rule "LogInserted"
        dialect "mvel"
        when
            l : LogItem ( )
        then
        System.out.println ("New Log inside from " + l.getSourceSystemName() );
    end

    rule "Nb Log SameSystem" 
        dialect "mvel"
        when
            accumulate( LogItem ( sourceSystemName == "GDE") over window:time(10s) ; $cnt: count(1); $cnt == 2 )
        then
        System.out.println ("2 Logs in engine" );
    end 

目标:在10秒的窗口中检测两个日志行。 第一个和第二个不是(11s),后面是2个,是的。

在实模式下,它可以正常工作。结果如下:

    LogItem { message : Message number 1, date : 28/03/2017 11:17:26, sourceSystemName : GDE }
    New Log inside from GDE
    LogItem { message : Message number 2, date : 28/03/2017 11:17:37, sourceSystemName : GDE }
    New Log inside from GDE
    LogItem { message : Message number 3, date : 28/03/2017 11:17:40, sourceSystemName : GDE }
    New Log inside from GDE
    2 Logs in engine
    LogItem { message : Message number 4, date : 28/03/2017 11:17:48, sourceSystemName : GDE }
    New Log inside from GDE
    2 Logs in engine

在伪时钟模式下,不会工作。因为4行是同时插入的,所以2首先激活规则。所以没有使用伪时钟。

结果如下:

    LogItem { message : Message number 1, date : 28/03/2017 11:17:26, sourceSystemName : GDE }
    New Log inside from GDE
    LogItem { message : Message number 2, date : 28/03/2017 11:17:37, sourceSystemName : GDE }
    New Log inside from GDE
    2 Logs in engine
    LogItem { message : Message number 3, date : 28/03/2017 11:17:40, sourceSystemName : GDE }
    New Log inside from GDE
    LogItem { message : Message number 4, date : 28/03/2017 11:17:48, sourceSystemName : GDE }
    New Log inside from GDE

我想这是因为我没有管理de伪时钟。但我无法找到我错的地方。

有人吗? 提前致谢;

1 个答案:

答案 0 :(得分:0)

我认为您的问题是由于对伪时钟的错误操作造成的。另外,为了获得最佳结果,请在自己的线程中运行会话,该线程执行fireUntilHalt:

Runnable fireUntilHaltRunnable = new Runnable() {
    public void run() {
        //      System.out.println( "fireUntilHalt" );
        kSession.fireUntilHalt()
    }
};
Thread fireUntilHaltThread = new Thread(fireUntilHaltRunnable);

事实是从另一个线程插入的。如果使用伪时钟运行测试,如果使用包含时间戳的事件作为字段,请确保将伪时钟设置为事件的时间戳:

private void advance( Date eventDate ){
    long currentTime = clock.getCurrentTime();
    long eventTime = eventDate.getTime();
    clock.advanceTime( eventTime - currentTime, TimeUnit.MILLISECONDS );
}

在之前执行此,插入下一个事实。插入之间无需睡眠。