I currently ran into a problem in our Drools server.
We receive pretty large requests to our drools server farm that throws an OutOfMemoryError. Those large request shouldn't be process (they are bugs), and if a request takes more than 5s it should be canceled.
I've trying to workaround this with a custom timeout DRL rule has explained here:
rule "Stop the rule engine after 5s"
timer ( int: 5s )
salience 0
when
then
System.err.println("*** Stop the rule engine after 5s ***");
drools.halt();
end
But this rule is never taking into account.
So I've tried another workaround: put my ksession.fireAllRules();in a thread, and if it takes more tahn 5 second, halt drools with ksession.halt();; like this:
KieSessionConfiguration conf = kieServices.newKieSessionConfiguration();
final KieSession ksession = kcontainer.newKieSession(conf);
Thread droolsThread = new Thread(new Runnable() {
public void run() {
ksession.fireAllRules();
}
}, "drools");
long tStart = System.currentTimeMillis();
droolsThread.start();
/*wait until the end of the Thread or 5 seconds max*/
while (System.currentTimeMillis() - tStart < 5000 && droolsThread.isAlive())
Thread.sleep(100);
/*if alive for more than 5 seconds stop it*/
if (droolsThread.isAlive())
{
System.err.println("timeout killing drools");
ksession.halt();
ksession.dispose();
}
In this second scenario, when drools is called with the ksession.fireAllRules();, it starts executing the request, and if this a huge one throws the Exception: java.lang.OutOfMemoryError exception:
[apache-tomcat-9.0.39]: timeout killing drools
[apache-tomcat-9.0.39]: Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "Catalina-utility-1"
java.lang.OutOfMemoryError: Java heap space
I don't know what to do to stop those large request eating all the server memory. Is it possible to stop a long request currently running in drools?
You were on the right track, but you need to start the rule execution using fireUntilHalt (instead of fireAllRules): https://docs.drools.org/7.40.0.Final/kie-api-javadoc/org/kie/api/runtime/rule/StatefulRuleSession.html#fireUntilHalt--
Then you will be able to stop it via halt method.
I would also advise into looking why you are seeing this pattern of "eating all the server memory". Maybe there will be opportunity to optimize your rules..
You could use the following API on a StatefulRuleSession:
fireAllRules(int max) Fire Matches on the Agenda up to the given maximum number of Matches, before returning the control to the application.
On consuming memory, you could profile the memory usage (at the Java level) to see what is going on. Rule-based applications generally use a lot of memory from making a memory-processing time trade-off using algorithms derived from RETE