Timer Drools基于计时器的规则在重新启动后多次触发

Timer Drools基于计时器的规则在重新启动后多次触发,timer,drools,rule-engine,drools-fusion,Timer,Drools,Rule Engine,Drools Fusion,我有一个场景,我想将规则纯粹用作调用其他服务的计划作业。我使用的解决方案与上的答案2类似。所以我有规则1,它看起来像: rule "ServiceCheck" timer ( int: 3m 5m ) no-loop true when then boolean isServiceEnabled = DummyServices.getServiceEnabledProperty(); if(isServiceEnabled){ ServicesCheck se

我有一个场景,我想将规则纯粹用作调用其他服务的计划作业。我使用的解决方案与上的答案2类似。所以我有规则1,它看起来像:

rule "ServiceCheck"

timer ( int: 3m 5m )

no-loop true
when
then
    boolean isServiceEnabled = DummyServices.getServiceEnabledProperty();
    if(isServiceEnabled){
        ServicesCheck servicesCheck = new ServicesCheck();      
        servicesCheck.setServiceEnabled(true);
        insert(servicesCheck);
    }
end
如果服务已启用,则每5分钟插入一个servicesCheck对象。一旦这个对象被插入,我的其他规则就会触发并从那里收回servicesCheck事实


我面临的问题是当我关闭应用程序并在第二天启动它时。此时,ServiceCheck规则在停止之前会被触发很多次。我的假设是,上次触发的时间保存在会话中,当我重新启动时,它会发现当前时间和保存的时间之间的差异,并触发规则的次数,直到会话中的2次匹配为止。因此,为了有效地弥补从关机到重启的1小时间隔,在这种情况下,它将触发规则12次,因为设置的间隔为5分钟。是否有一种方法可以用来更新规则会话上上次触发的时间,以便它像一个新的开始一样开始工作,而不必补上丢失的时间。

我想您正在持续整个会话?我想你有一个关机程序。您可以使用一个事实,我们称之为
Trigger
。将规则修改为

rule "ServiceCheck"
  timer ( int: 3m 5m )
when
  Trigger()
then
  // ... same
end
您必须在启动后插入一个触发器事实,并在关机时收回它

以后

我已经设置了一个实验(使用5.5.0),其中一个会话正在运行,在一个线程中使用fireUntilHalt调用,并使用类似“ServiceCheck”的规则。另一个线程将休眠一段时间,在收回触发器事实后停止会话。在定时器触发的间隔超过两倍后,第二个线程再次插入触发器,向第一个线程发出重新进入fireUntilHalt()的信号,第二个线程将重复其循环我可以在扳机收回期间观察到静音。

但是,如果没有收回/重新插入触发器,则会话重新启动后会出现一系列触发


这表明收回和重新插入触发器确实会停止并重新启动计时器规则。

我也想到了这一点,但这增加了一个额外的要求,即在整个应用程序正常运行期间保持事实参考可用,以便在关机时收回。对于像我这样的情况,有没有最佳实践来使用“when”为空(eval(true))的规则?你不能回避逻辑。正如您所说,空的“when”部分仅表示“true”,这意味着计时器确实应该每隔一段时间触发一次。如果你不想这样,你就必须创造一个能反映你需要的条件。这是一个逻辑指令,你不能逃避…——然而,如果你不能/不想处理正确使用规则的后果,为什么要使用规则?Java将允许您进行同样的设置。感谢您的更新。您昨天提供的方法工作得很好。事实上,作业会停止,不会产生不必要的激活。因此,我认为我最终需要使用事实来实现这一点。我试图将第一条规则纯粹用作插入触发其余作业的事实的cron作业,它工作正常,但在重新启动时会出现问题。我还使用了AgendaEventListener,它显示了正常作业的激活情况。它没有显示服务器重新启动时引发的事件的任何内容。感谢您的帮助。顺便说一句:我想表达我对以下问题的不同意见,这些问题的适当答案用“我也想到过这一点”一开始就没有指出这一点。只是浪费我的时间,是吗?在规则触发问题开始遵循间隔之前,我已经代表了特定的次数。问题不在于条件,因为规则在与时钟同步后工作完全正常。你提出条件的解决方案也不能解决这个问题。如果你觉得这是浪费你的时间,请跳过我的问题,但我看不出有理由-1我的问题。请解释为什么插入和删除“触发器”事实并不能解决你的问题。我知道你只是不希望管理这个事实会带来(小的)额外开销。而且,你所体验到的效果可能取决于你正在使用的Drools版本-它是哪一个?另外,您还没有确认是否坚持会话,也没有解释如何停止并重新启动“应用程序”-或者只是知识/会话?谢谢您的回复。是的,我在使用jBPM的同时也会持久化整个会话。Drools的版本是5.5.0 Final。singleton会话是使用jBPM API自动保存的。因为我使用的是timer对象,所以我看到timer将下一个fire时间戳设置为setNextFireTimestamp(trigger.hasNextFireTime().getTime())。因此,如果此时间设置为18:00,并且我们在17:59停止应用程序(以及内部会话),并在18:11启动它,则触发器会为以下创建的计划(180018051810)触发3次。即使我们使用了事实,也会发生这种情况。