DRools:无循环 true 属性不适用于 update() 方法推断

DRools: no-loop true attribute not working with update() method inference

我有一个简单的 DRools 包,其中包含一条规则,其 DRL 源如下:

package com.rules.standard.isolatesFlags.GRUPPI_FAMIGLIE;

import org.package.path.ResultIsolate;

global org.apache.log4j.Logger logger;

function void finalizeIsolate(ResultIsolate isolate, Logger logger) {
    /* implementation */
}

function void setIsolateCSIFlag(ResultIsolate isolate, Integer csiAlarm, Logger logger) {
    /* implementation */
}

rule "ConfirmEsccolWasplab" 
    dialect "mvel"
    salience 10
    enabled true
    no-loop true

    when
      $a : ResultIsolate( deviceId == "WASPLAB_core" , microId == "h_W_ESCO" )
      $b : ViewPlateResult( plateStatus >= 60 , plateCode == "h_CCA" ) from $a.isolatePlates

    then
      finalizeIsolate($a,logger);
      setIsolateCSIFlag($a,new Integer(-1),logger);
      update($a);
end

然后,在我的 Java EJB 中,我执行如下规则:

kSession = kbase.newStatefulKnowledgeSession();
kSession.addEventListener(ruleListener);
            
logger.debug("Injecting global variabiles isTest and logger and EJB MicroRulesUtils into StatefulKnowledgeSession");
kSession.setGlobal("logger", org.apache.log4j.Logger.getLogger(MicroBusinessIsolateFlagsImpl.class));
                
kSession.insert(resultIsolate);
kSession.fireAllRules((int)MicroBusinessIsolateFlags.MAX_FIREABLE_RULES); //1000

ruleListener 是一个实现 AgendaEventListener 接口的 vlass,在方法 beforeActivationFired 的实现中,我计算了每个事实激活和触发的规则数量。 事实上,在我的 EJB 中,在触发规则之后,我检查:

if(ruleListener.getNumberOfFiredRules() >= MAX_FIREABLE_RULES) {
    logger.info("Isolate flags rules fired more than ",MicroBusinessIsolateFlags.MAX_FIREABLE_RULES, " times. Check configuration to prevent inference loops from occurring.");
    logger.info(ruleListener.getRulesActivationsLog()); //print fired rules and how many times
}

因此,总是会显示此警告。这怎么可能?正如我所说,我有一个包含单个规则和 no-loop true 属性的包,我希望规则本身不会因其 RHS 而被激活。但它是。那是一个错误吗? 此外,在添加其他未激活的包规则(包含的规则的条件不匹配)之后,我总是将这些规则记录为已触发 1000 次(循环)。 我正在使用 DRools 5.0.1 并且不允许升级它。

不,这不是错误。这就是该功能的工作原理。

调用 update 在功能上等同于调用 'fireRules'。就好像我们退出了当前的 'fire rules' 流程,然后使用新数据重新运行所有规则。由于是新的 运行,没有以前的执行,所以 no-loop 不适用。

这是与 insert(例如)的对比。当您在规则的 RHS 中调用 insert 时,引擎只会重新评估 当前 运行 中的后续规则。在这种情况下,'no-loop'确实适用,因为我们仍然处于相同的运行,并且之前的执行仍然存在。

no-loop 旨在防止同一规则在一次规则执行中多次触发。它并不是为了防止规则在多次执行中触发。

要使您的规则不在更新时触发,您需要修改左侧以排除右侧设置的条件。由于您省略了 setIsolateCSIFlag 函数的定义,因此我将编写一个简单的示例:

rule "EXAMPLE"
no-loop
when
  Address( $locality: locality )
  $purchase: Purchase( sum > 0, tax == null )
then
  $purchase.calcualteTaxForLocality($locality); // sets 'tax' to some value
  update( $purchase );
end

由于 Purchase 实例现在有一个非空 tax 值,因此在 update 之后规则不会再次触发。在您的情况下,您应该根据 setIsolateCSIFlag 方法实际执行的任何操作更新条件 (LHS) 以不触发。或者,也不要调用 update.