我的定时规则不会触发 Drools 6.1。0.Final

My timed rule wont fire Drools 6.1.0.Final

我有两条规则。这是 Drools 6.1.0.Final

rule "HandleSomeEvent"
salience 5
no-loop
when
    $eventA  : SomeEvent()
then
    MyClass.handleSomeEvent($eventA); 
end


rule "HandleSomeEventRetry"
    timer(int: 15m 15m)  
    no-loop
    when
        $eventA  : SomeEvent()
    then
        MyClass.handleSomeEvent($eventA);
end

这些规则的测试在 Drools 5.1.1 中没有问题,但我正在尝试重构到 6.1。0.Final。在我的测试中 class 我设置了一个 KieSession

    KieServices ks = KieServices.Factory.get();
    KieContainer kContainer = ks.getKieClasspathContainer();

    KieBaseConfiguration kBaseConfig = ks.newKieBaseConfiguration();
    kBaseConfig.setOption(EqualityBehaviorOption.EQUALITY);
    KieBase kBase = kContainer.newKieBase(kBaseConfig);

    KieSessionConfiguration kSessionConfig =   ks.newKieSessionConfiguration();
    kSessionConfig.setOption(ClockTypeOption.get("pseudo"));

    ksession = kBase.newKieSession(kSessionConfig, null);

    SessionPseudoClock clock = ksession.getSessionClock();
    ksession.setGlobal("MyClass", MyClass);

我在这个单元测试中进行了测试,验证所有规则在事件通过时触发,并且它们都通过了定时重试事件。我尝试测试handle事件,重试如下

    SomeEvent e...
    AgendaEventListener ael = mock(AgendaEventListener.class);
    ksession.addEventListener(ael);
    ksession.insert(e);
    ksession.fireAllRules();

    clock.advanceTime(15, TimeUnit.MINUTES);

    ArgumentCaptor<AfterMatchFiredEvent> amfe = ArgumentCaptor.forClass(AfterMatchFiredEvent.class);
    verify(ael, times(2)).afterMatchFired(amfe.capture());

在使用 5.1.1 进行测试时,我还可以从 ArgumentCaptor 中获取事件并验证触发的各个规则的名称。第一个是初始的,第二个是定时重试。然而,对于 6.1.0.Final,甚至只会触发一个 Match。我找不到任何文档来支持这一点,但是 6.1 中的定时事件有很大的改变吗?我已经放入调试行来验证时间提前和之后事件是否仍然存在,但是定时事件不会触发。

确实发生了变化,因为 (IIRC) Drools 团队似乎不喜欢由此产生的效果 and/or 未完全定义的计时器语义 运行 而规则引擎 活跃。 (请注意,您可以在一个会话中重复调用 session.fire*()。)

在移动到 6.x 时,决定在引擎未 运行 时暂停触发计时器控制规则的激活。

您可以(使用您的规则,但使用 String 作为事实):

        kieSession.insert( "Some fact" );
        kieSession.fireAllRules();
        System.out.println("sleep");
        Thread.sleep( 8000 );
        System.out.println("wake-up");
        kieSession.fireUntilHalt();

您会观察到进入睡眠间隙的 "retry" 的触发被延迟到唤醒之后(并且未能遵守计时器中定义的时间)。

但如果您立即调用 fireUntilHalt,一切都会正常进行。您可能必须添加另一种机制才能正常关机。