如何解决流口水的法则在不应该维持状态和解雇规则的情况下
我遇到了一个问题,即规则不更新状态并在不应该触发时触发,我只希望规则在两个开关都打开时才触发。
For example:
In the following order I
open switcha
close switcha
open switchb
在不应该关闭switcha时触发规则。尽快出现 Switch(name ==“ switcha”,status ==“ Open)变为true,即使再次关闭开关也保持此状态。
rule "Electrical Circuit Status"
when
Switch( name == "switcha",status == "Open" )
and
Switch( name == "switchb",status == "Open" )
then // Raise Alert
** Didn't write this code out as it works fine
end
感谢您的帮助。
解决方法
您可能会误解工作记忆状态。但是,由于您的问题对细节的要求极低,因此我将在解释中做出几个假设,这些假设将在下面列出。
假设我们有两个处于以下状态的开关:
-
Switch( name == "switcha",status == "Closed")
-
Switch( name == "switchb",status == "Closed")
我们将这些开关原样传递到我们的规则中。
当我们在云模式下运行时,规则是在时间的瞬间而不是在一段时间内执行的(这将是流模式)。云模式是默认模式,也是大多数应用程序利用的模式。由于您没有提及事件流,因此我将假设您正在此模式下运行。 (如果您不知道我在说什么,那么您也可能会在Cloud模式下运行; Stream模式是一个相对较新的功能。)我还将承担一个有状态的会话。
当我们调用fireAllRules
时,Drools将查看规则输入并找出哪些规则具有与这些条件匹配的条件。将使用该规则的子集,根据显着性和自然顺序找出它们的顺序,然后执行它们。
在执行这些规则时,您可以通过多种方式修改规则输入。
- 致电
insert
。这将新事实添加到工作记忆中。 - 致电
modify
。这将更改现有的事实数据。 - 致电
update
。这也会更改现有的事实数据。 - 直接更改对象上的数据,例如通过getter或setter。
取决于更改数据的方式,这可能会或可能不会更改规则的评估方式。
如果您直接更改数据(例如,通过getter或setter更改),则不会对规则进行任何重新评估。任何更改在功能上对于Drools引擎都是“不可见的”。即使条件不再成立,仍会触发最初被识别为匹配的规则,因为您更新数据的方式不会导致Drools重新评估这些条件。
如果您致电update
,Drools将重新评估整个规则范围。这在功能上等同于更改数据,然后从顶部再次重新定义规则。 Drools将使用工作内存中的新数据查看所有规则,并重做收集匹配,排序和触发它们的过程。使用update
调用很容易进入“循环”状态。
如果您调用insert
,则是将新的数据添加到工作存储器中。 Drools将对规则进行部分重新评估,以确定是否有符合条件的新规则可以触发,或者以前的匹配项现在是否无效。它不会重新触发以前匹配并被触发的任何规则。同样,如果您调用modify
,则会以某种方式更改现有规则输入对象的属性,因此Drools将根据更改的条件部分重新评估。
(这已简化。您可以通过阅读源代码或文档来了解有关细微差别的更多信息。)
由于您只显示了一条局部规则,并且只说即使在“再次关闭开关时”也会触发,尽管没有说明关闭开关的方式,所以我可以提出几种可能的方法根据前面关于如何在有(或没有)重新评估规则条件的情况下更改数据的解释触发此条件。
例如,如果通过调用setStatus("Closed")
方法而不是通过使用modify
来更改开关状态,则规则将不知道新状态。
rule "change switch state invisibly"
when
// some conditions
$b: Switch( name == "switchb",status == "Open" )
then
$b.setStatus("Closed");
end
rule "Electrical Circuit Status"
Switch( name == "switcha",status == "Open" ) // let's assume this is true
Switch( name == "switchb",status == "Open" ) // Also still true!
then
// show alert
end
由于您使用setStatus
而不是modify
来更改状态,因此Drools不会重新评估后续的规则匹配,而是保留先前的匹配。因此条件仍然成立。
要解决此问题,在更改后,您应该使用modify
或(建议不要使用)update
的工作记忆(但要理解,将重新评估所有 规则) )
modify ($b) {
setStatus("Closed")
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。