为什么这个流口水的场景会导致无限循环?

e0uiprwp  于 2021-06-27  发布在  Java
关注(0)|答案(1)|浏览(342)

我正在写一个drools中的规则集,以下情况会通过重新触发规则导致无限循环:

rule "My Rule"
    when
        a1:ObjectA()
        b1:ObjectB(field1 > 0 || a1.field1 in (1,2,3))
        ObjectB(field2 > 10)
    then
        modify( b1 ) { setField3(5) };
end

以下规则更改不会导致无限循环,即当a1不再在objectb中引用时:

rule "My Rule"
    when
        b1:ObjectB(field1 > 0 || field4 in (1,2,3))
        ObjectB(field2 > 10)
    then
        modify( b1 ) { setField3(5) };
end

另一个不会引起无限循环的场景是当我改变 || 到一个 && 在第二个 when 生产线:

rule "My Rule"
    when
        a1:ObjectA()
        b1:ObjectB(field1 > 0 && a1.field1 in (1,2,3))
        ObjectB(field2 > 10)
    then
        modify( b1 ) { setField3(5) };
end

从drools医生那里我明白 modify(){} 将“触发重新评估知识库中匹配对象类型的所有模式”,但由于我正在修改字段, field3 ,没有在lhs条件下使用,我不认为应该重新评估。然而,我不能肯定这与引用有关 a1.field1ObjectB ,但我找不到具体的原因。提前谢谢!

c8ib6hqw

c8ib6hqw1#

它在对象级别重要,而不是字段级别。因为你修改了 a1 ,则重新计算规则,因为它依赖于工作内存中的objecta对象。请注意,文档指示它将“触发对知识库中匹配对象类型的所有模式的重新评估”,而不是参数值。
可以避免这种情况的一种方法是添加如下约束 field3 != 5 在左手边。即:

rule "My Rule"
when
  a1: ObjectA( field3 != 5 ) // <-- if field3 is already 5, don't fire the rule
  b1: ObjectB(field1 > 0 || a1.field1 in (1,2,3))
  exists(ObjectA(field2 > 10))
then
  modify( a1 ) { setField3(5) };
end

基本上,你需要使规则不再有资格重新开火。
或者,根据您的结构,您可以尝试使用 no-loop ,但这只会防止规则在右手边立即触发时被刷新。如果您有多个修改/更新等,您可能会进入一个“更广泛的”循环场景,其中多个规则会导致重新评估(示例:规则a进行重新计算,没有循环阻止a再次触发;然后b导致重新评估,因此a可以触发,因为没有循环不适用。)

相关问题