]
Edson Tirelli reassigned DROOLS-2240:
-------------------------------------
Assignee: Mario Fusco (was: Edson Tirelli)
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.