如何解决为什么这个 Drools 场景会导致无限循环?
我正在 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
以下规则更改不会导致无限循环,即在 ObjectB 中不再引用 a1 时:
rule "My Rule"
when
b1:ObjectB(field1 > 0 || field4 in (1,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,3))
ObjectB(field2 > 10)
then
modify( b1 ) { setField3(5) };
end
从 Drools docs 我了解到调用 modify(){}
将“触发对知识库中匹配对象类型的所有模式的重新评估”,但由于我正在修改的字段,{{ 1}},未用在LHS条件下,我认为不应该重新评估。但是,我不确定它是否与在 field3
中引用 a1.field1
有关,但我找不到具体的原因。提前致谢!
解决方法
它在对象级别很重要,而不是字段级别。由于您修改了 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 可以触发,因为无循环不适用。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。