我在使用伪时钟运行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伪时钟。但我无法找到我错的地方。
有人吗? 提前致谢;
答案 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 );
}
在之前执行此,插入下一个事实。插入之间无需睡眠。