英文:
how to implement time persistence in drools?
问题
我对Drools还不熟悉,我想知道是否有一种方法可以编写表达时间持续性的规则:
如果(条件在X秒内为真)则执行某些操作。
规则 "示例"
当
r: Room(Temperature > 100, this over window:time(10m))
然后
doSomething()
end
英文:
I am new to drools and I was wondering if there was a way to write rules that express persistence in time : <br>
if (condition true for X seconds) then doSomething()
Rule "Example"
when
r: Room(Temperature > 100 for 10 minutes )
then
doSomething()
end
答案1
得分: 0
有两种模式可以触发 Drools 规则 —— 默认模式是“云”模式,在此模式下,我们在单个时间点评估工作内存中的所有事实。这是最古老且最常用的触发规则的方式。另一种模式是“流”模式,其中数据持续播放,Drools 引擎能够感知时间。
在流模式下,Drools 拥有一组时间操作符(链接至 Drools 文档),可以用来针对随时间发生的事实编写条件。
您可以按照以下方式为您的用例使用时间操作符:
rule "检测持续 10 分钟内温度超过 100 度"
when
$t: Temperature(this >= 100) from entry-point "TemperatureStream"
not(
Temperature(
this != $t,
this < 100,
this after[0s,10m] $t) from entry-point "TemperatureStream")
then
doSomething()
end
这个简单的规则期望您通过某种外部机制从入口点(TemperatureStream
)发送温度事件。当它检测到温度超过 100 度(实例 $t
)时,第一个条件触发。
第二个条件是关键所在。只有当在接收到 $t
后的 10 分钟内未接收到温度低于 100 度的事件时,第二个条件才会触发。
当监控应用程序发送温度事件时,每个超过 100 度的事件都会触发第一个条件,然后开始监视流以查看第二个条件是否成立。如果成立,规则的结果将被触发。否则,规则匹配将被丢弃。
或者,您可以使用滑动窗口在 10 分钟内查看温度最低值是否曾低于 100 度。
rule "检测持续 10 分钟内温度超过 100 度 - 滑动窗口"
when
not(
Number(doubleValue < 100) from accumulate(
Room( $temperature: Temperature ) over window:time(10m),
min( $temperature )
)
)
then
doSomething()
end
这里的 window:time(10m)
是在 10 分钟时间段内的滑动窗口。与其他解决方案不同,其他解决方案在每次事件进来时观察它,然后尝试检查第二个条件是否匹配,而这个解决方案只是在一段时间内查看所有事件。如果整个窗口内的最低温度从未低于 100 度,右侧条件将触发。
这可能还有其他的方法,上述只是我即兴想到的两种方法。Drools 的这一部分文档特别详细,您可能会找到更适合您用例的方法。
英文:
There are two modes for firing Drools rules -- the default is "Cloud" mode, where we evaluate all of the facts in working memory at a single point in time. This is the oldest and most common way to fire rules. The other mode is "stream" mode, where data is played in continuously, and the Drools engine is aware of time.
When in stream mode, Drools has a set of temporal operators (link to Drools documentation) which can be used to write conditions against facts which occur over time.
One way that you can use the temporal operators for your use case would be as follows:
rule "Detect temperature over 100 for 10 minutes"
when
$t: Temperature(this >= 100) from entry-point "TemperatureStream"
not(
Temperature(
this != $t,
this < 100,
this after[0s,10m] $t) from entry-point "TemperatureStream")
then
doSomething()
end
This simple rule expects that you're sending Temperature events from an entrypoint (TemperatureStream
) via some external mechanism. When it detects a temperature over 100 degrees (instance $t
), the first condition triggers.
The second condition is where the magic happens. The second condition will only trigger if it does not receive a Temperature event of less than 100 degrees in the 10 minutes following the receipt of $t
.
As your monitoring application sends temperature events, each one over 100 will trigger the first condition, and then start monitoring the stream to see if the second holds true. If it does, the consequence of the rule will fire. Otherwise the rule match will be discarded.
Alternatively, you could use a sliding window over 10 minutes to see if the temperature minimum ever drops below 100.
rule "Detect temperature over 100 for 10 minutes - sliding window"
when
not(
Number(doubleValue < 100) from accumulate(
Room( $temperature: Temperature ) over window:time(10m),
min( $temperature )
)
)
then
doSomething()
end
Here, window:time(10m)
is a sliding window over a 10 minute period. Unlike the other solution which observes each even as it comes in, and then tries to check if a second condition matches, this one simply looks at all events over a period of time. If the minimum temperature never goes below 100 for the entire window, the right hand side triggers.
There's probably other ways of doing this, these are just the two that I came up with offhand. The documentation is particularly good for this part of Drools, so you might find another way that better fits your use case.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论