简体   繁体   中英

Drools timer based rule session always resides in memory and cause memory leak

I'm a newbie to Drools. I want to delay 5s after I fired the rule (and just for one time). So, I use timer(int:5s) to do that. But I found that after the rule executed, my console application will never be terminated and its javaw.exe process still exist in my task manager. The only one way is to call ksession.dispose(). But it's not acceptable because it's hard to find this ksession in our clustering architect.

So, is there any way to make the ksession automatically disposed after the rule executed?

Here are my simple test case:

  1. main class

     public class App { public static void main( String[] args ) { System.out.println("Started..."); KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(); kbuilder.add(new ClassPathResource("Timer.drl", App.class), ResourceType.DRL); KnowledgeBase kbase = kbuilder.newKnowledgeBase(); StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession(); ksession.fireAllRules(); System.out.println("Ended"); } } 
  2. drl file

     package myDrools.TimerTest1 rule "Your First Rule" timer(int:5s) when eval(true) then System.out.println("Finished"); end 

    The output will be:

     Started... Ended Finished 

But my console application will never be terminated. Is there something wrong? I tested it both in Drools 5.6.0 Final and 6.4.0 Final. However, both of them has the same issue. I think the ksession should be disposed since timer(int:5s) is not an interval timer.

Timers run in parallel to the thread hosting the session and keep the session alive. In a way, they are meant to be used in sessions running indeterminate, ie, not started calling fireAllRules.

The following scenario should give you a clean shutdown:

rule  "Your First Rule"
  timer( int:5s )
when
then
  System.out.println("Finished");
  drools.halt();
end

And your session is started like this:

kieSession.fireUntilHalt();
System.out.println( "return from fireUntilHalt" );
kieSession.dispose();

Edit

If you need to call halt in any case you can add another rule with the negated condition which calls halt right away.

rule "stop if not met"
when
    // negated condition X
then
    drools.halt();
end  

Hint: The negated condition X is not not X !

Based on laune's great answer, I modified my drl file to make sure the drools.halt() will always be hit. (Note: v6.4.0 Final is OK. But v5.6.0 Final will throw exception for do clause)

dialect "mvel"
rule "Hello World"
timer(int:5s)
when
    m : Message()
    if ( m.status == Message.HELLO)
    do[hello]
then
    System.out.println( "other status" );
    drools.halt();
then[hello]
    System.out.println( "Hello!" );
    drools.halt();

end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM