]
Mario Fusco resolved DROOLS-2240.
---------------------------------
Resolution: Explained
You have a rule that is fires every second, have a pseudo-clock that makes a jump of 10
seconds in one shoot and expect the rule to fire 10 times. This is not how the
psuedo-clock is supposed to work. Conversely time conditions are evaluated once at each
discrete jump so what happens when you do 10 seconds jump is that the timestamp for the
next expected rule firing is compared with the current time and if it's lower the rule
fires once and that's all. When instead of do 10 subsequent jumps the condition is
evaluated 10 times and then also the rule fires 10 times as per your expectations.
Timer rules with pseudo clock don't fire
----------------------------------------
Key: DROOLS-2240
URL:
https://issues.jboss.org/browse/DROOLS-2240
Project: Drools
Issue Type: Bug
Affects Versions: 7.5.0.Final
Reporter: Christian Bauer
Assignee: Mario Fusco
We are trying to test rules with timer option and the pseudo clock.
The problem can probably also be seen by enabling (note the @Ignore) this test:
https://github.com/kiegroup/drools/blob/master/drools-compiler/src/test/j...
Based on this class, this is a minimal test that shows the problem:
{code}
import org.drools.core.time.SessionPseudoClock;
import org.junit.Test;
import org.kie.api.KieServices;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieModuleModel;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.conf.ClockTypeOption;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.assertEquals;
/**
* Based on:
*
https://github.com/kiegroup/drools/blob/master/drools-compiler/src/test/j...
*/
public class PseudoClockTimerTest {
private KieSession ksession;
private SessionPseudoClock clock;
public void init(String clockType) {
String drl = "package test.rules\n" +
"\n" +
"rule \"Do something triggered by timer\"\n" +
"timer (int: 1s 1s)\n" +
"then\n" +
" System.out.println(\"### DO SOMETHING \" +
drools.getWorkingMemory().getSessionClock().getCurrentTime());\n" +
" insert(\"### TIME IS \" +
drools.getWorkingMemory().getSessionClock().getCurrentTime());\n" +
"end\n";
KieServices ks = KieServices.Factory.get();
KieModuleModel module = ks.newKieModuleModel();
KieBaseModel defaultBase = module.newKieBaseModel("defaultKBase")
.setDefault(true)
.addPackage("*");
defaultBase.newKieSessionModel("defaultKSession")
.setDefault(true)
.setClockType(ClockTypeOption.get(clockType));
KieFileSystem kfs = ks.newKieFileSystem()
.write("src/main/resources/r1.drl", drl);
kfs.writeKModuleXML(module.toXML());
ks.newKieBuilder(kfs).buildAll();
ksession = ks.newKieContainer(ks.getRepository().getDefaultReleaseId())
.newKieSession();
if (clockType.equals("pseudo"))
clock = ksession.getSessionClock();
}
public void cleanup() {
ksession.dispose();
}
@Test
public void testTimerExecution() throws Exception {
init("realtime");
performRealtimeClockTest();
cleanup();
init("pseudo");
performPseudoClockTest();
cleanup();
}
private void performRealtimeClockTest() throws Exception {
ExecutorService thread = Executors.newSingleThreadExecutor();
final Future fireUntilHaltResult = thread.submit(() ->
ksession.fireUntilHalt());
try {
Thread.sleep(10500);
assertEquals(10, ksession.getFactCount());
} finally {
ksession.halt();
fireUntilHaltResult.get(60000, TimeUnit.SECONDS);
thread.shutdown();
}
}
private void performPseudoClockTest() throws Exception {
ExecutorService thread = Executors.newSingleThreadExecutor();
final Future fireUntilHaltResult = thread.submit(() ->
ksession.fireUntilHalt());
try {
Thread.sleep(500);
// NOT WORKING:
// clock.advanceTime(10, TimeUnit.SECONDS);
// Thread.sleep(50);
// WORKAROUND:
for (int i = 0; i < 10; i++) {
clock.advanceTime(1, TimeUnit.SECONDS);
Thread.sleep(50);
}
assertEquals(10, ksession.getFactCount());
} finally {
ksession.halt();
fireUntilHaltResult.get(60000, TimeUnit.SECONDS);
thread.shutdown();
}
}
}
{code}
See the NOT WORKING and WORKAROUND markers. There doesn't seem to be any other test
in the codebase with timer rules and the pseudo clock, so our conclusion is that this
combination is not working at all.